clang  15.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 struct StaticDiagInfoRec;
30 
31 // Store the descriptions in a separate table to avoid pointers that need to
32 // be relocated, and also decrease the amount of data needed on 64-bit
33 // platforms. See "How To Write Shared Libraries" by Ulrich Drepper.
34 struct StaticDiagInfoDescriptionStringTable {
35 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
36  SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
37  char ENUM##_desc[sizeof(DESC)];
38  // clang-format off
39 #include "clang/Basic/DiagnosticCommonKinds.inc"
40 #include "clang/Basic/DiagnosticDriverKinds.inc"
41 #include "clang/Basic/DiagnosticFrontendKinds.inc"
42 #include "clang/Basic/DiagnosticSerializationKinds.inc"
43 #include "clang/Basic/DiagnosticLexKinds.inc"
44 #include "clang/Basic/DiagnosticParseKinds.inc"
45 #include "clang/Basic/DiagnosticASTKinds.inc"
46 #include "clang/Basic/DiagnosticCommentKinds.inc"
47 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
48 #include "clang/Basic/DiagnosticSemaKinds.inc"
49 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
50 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
51  // clang-format on
52 #undef DIAG
53 };
54 
55 const StaticDiagInfoDescriptionStringTable StaticDiagInfoDescriptions = {
56 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
57  SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
58  DESC,
59 // clang-format off
60 #include "clang/Basic/DiagnosticCommonKinds.inc"
61 #include "clang/Basic/DiagnosticDriverKinds.inc"
62 #include "clang/Basic/DiagnosticFrontendKinds.inc"
63 #include "clang/Basic/DiagnosticSerializationKinds.inc"
64 #include "clang/Basic/DiagnosticLexKinds.inc"
65 #include "clang/Basic/DiagnosticParseKinds.inc"
66 #include "clang/Basic/DiagnosticASTKinds.inc"
67 #include "clang/Basic/DiagnosticCommentKinds.inc"
68 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
69 #include "clang/Basic/DiagnosticSemaKinds.inc"
70 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
71 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
72  // clang-format on
73 #undef DIAG
74 };
75 
76 extern const StaticDiagInfoRec StaticDiagInfo[];
77 
78 // Stored separately from StaticDiagInfoRec to pack better. Otherwise,
79 // StaticDiagInfoRec would have extra padding on 64-bit platforms.
80 const uint32_t StaticDiagInfoDescriptionOffsets[] = {
81 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
82  SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
83  offsetof(StaticDiagInfoDescriptionStringTable, ENUM##_desc),
84 // clang-format off
85 #include "clang/Basic/DiagnosticCommonKinds.inc"
86 #include "clang/Basic/DiagnosticDriverKinds.inc"
87 #include "clang/Basic/DiagnosticFrontendKinds.inc"
88 #include "clang/Basic/DiagnosticSerializationKinds.inc"
89 #include "clang/Basic/DiagnosticLexKinds.inc"
90 #include "clang/Basic/DiagnosticParseKinds.inc"
91 #include "clang/Basic/DiagnosticASTKinds.inc"
92 #include "clang/Basic/DiagnosticCommentKinds.inc"
93 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
94 #include "clang/Basic/DiagnosticSemaKinds.inc"
95 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
96 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
97  // clang-format on
98 #undef DIAG
99 };
100 
101 // Diagnostic classes.
102 enum {
103  CLASS_NOTE = 0x01,
104  CLASS_REMARK = 0x02,
105  CLASS_WARNING = 0x03,
106  CLASS_EXTENSION = 0x04,
107  CLASS_ERROR = 0x05
108 };
109 
110 struct StaticDiagInfoRec {
111  uint16_t DiagID;
112  uint8_t DefaultSeverity : 3;
113  uint8_t Class : 3;
114  uint8_t SFINAE : 2;
115  uint8_t Category : 6;
116  uint8_t WarnNoWerror : 1;
117  uint8_t WarnShowInSystemHeader : 1;
118  uint8_t WarnShowInSystemMacro : 1;
119 
120  uint16_t OptionGroupIndex : 15;
121  uint16_t Deferrable : 1;
122 
123  uint16_t DescriptionLen;
124 
125  unsigned getOptionGroupIndex() const {
126  return OptionGroupIndex;
127  }
128 
129  StringRef getDescription() const {
130  size_t MyIndex = this - &StaticDiagInfo[0];
131  uint32_t StringOffset = StaticDiagInfoDescriptionOffsets[MyIndex];
132  const char* Table = reinterpret_cast<const char*>(&StaticDiagInfoDescriptions);
133  return StringRef(&Table[StringOffset], DescriptionLen);
134  }
135 
136  diag::Flavor getFlavor() const {
137  return Class == CLASS_REMARK ? diag::Flavor::Remark
139  }
140 
141  bool operator<(const StaticDiagInfoRec &RHS) const {
142  return DiagID < RHS.DiagID;
143  }
144 };
145 
146 #define STRINGIFY_NAME(NAME) #NAME
147 #define VALIDATE_DIAG_SIZE(NAME) \
148  static_assert( \
149  static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) < \
150  static_cast<unsigned>(diag::DIAG_START_##NAME) + \
151  static_cast<unsigned>(diag::DIAG_SIZE_##NAME), \
152  STRINGIFY_NAME( \
153  DIAG_SIZE_##NAME) " is insufficient to contain all " \
154  "diagnostics, it may need to be made larger in " \
155  "DiagnosticIDs.h.");
156 VALIDATE_DIAG_SIZE(COMMON)
157 VALIDATE_DIAG_SIZE(DRIVER)
158 VALIDATE_DIAG_SIZE(FRONTEND)
159 VALIDATE_DIAG_SIZE(SERIALIZATION)
161 VALIDATE_DIAG_SIZE(PARSE)
164 VALIDATE_DIAG_SIZE(CROSSTU)
165 VALIDATE_DIAG_SIZE(SEMA)
167 VALIDATE_DIAG_SIZE(REFACTORING)
168 #undef VALIDATE_DIAG_SIZE
169 #undef STRINGIFY_NAME
170 
171 const StaticDiagInfoRec StaticDiagInfo[] = {
172 // clang-format off
173 #define DIAG(ENUM, CLASS, DEFAULT_SEVERITY, DESC, GROUP, SFINAE, NOWERROR, \
174  SHOWINSYSHEADER, SHOWINSYSMACRO, DEFERRABLE, CATEGORY) \
175  { \
176  diag::ENUM, \
177  DEFAULT_SEVERITY, \
178  CLASS, \
179  DiagnosticIDs::SFINAE, \
180  CATEGORY, \
181  NOWERROR, \
182  SHOWINSYSHEADER, \
183  SHOWINSYSMACRO, \
184  GROUP, \
185  DEFERRABLE, \
186  STR_SIZE(DESC, uint16_t)},
187 #include "clang/Basic/DiagnosticCommonKinds.inc"
188 #include "clang/Basic/DiagnosticDriverKinds.inc"
189 #include "clang/Basic/DiagnosticFrontendKinds.inc"
190 #include "clang/Basic/DiagnosticSerializationKinds.inc"
191 #include "clang/Basic/DiagnosticLexKinds.inc"
192 #include "clang/Basic/DiagnosticParseKinds.inc"
193 #include "clang/Basic/DiagnosticASTKinds.inc"
194 #include "clang/Basic/DiagnosticCommentKinds.inc"
195 #include "clang/Basic/DiagnosticCrossTUKinds.inc"
196 #include "clang/Basic/DiagnosticSemaKinds.inc"
197 #include "clang/Basic/DiagnosticAnalysisKinds.inc"
198 #include "clang/Basic/DiagnosticRefactoringKinds.inc"
199 // clang-format on
200 #undef DIAG
201 };
202 
203 } // namespace
204 
205 static const unsigned StaticDiagInfoSize = llvm::array_lengthof(StaticDiagInfo);
206 
207 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
208 /// or null if the ID is invalid.
209 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
210  // Out of bounds diag. Can't be in the table.
211  using namespace diag;
212  if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)
213  return nullptr;
214 
215  // Compute the index of the requested diagnostic in the static table.
216  // 1. Add the number of diagnostics in each category preceding the
217  // diagnostic and of the category the diagnostic is in. This gives us
218  // the offset of the category in the table.
219  // 2. Subtract the number of IDs in each category from our ID. This gives us
220  // the offset of the diagnostic in the category.
221  // This is cheaper than a binary search on the table as it doesn't touch
222  // memory at all.
223  unsigned Offset = 0;
224  unsigned ID = DiagID - DIAG_START_COMMON - 1;
225 #define CATEGORY(NAME, PREV) \
226  if (DiagID > DIAG_START_##NAME) { \
227  Offset += NUM_BUILTIN_##PREV##_DIAGNOSTICS - DIAG_START_##PREV - 1; \
228  ID -= DIAG_START_##NAME - DIAG_START_##PREV; \
229  }
230 CATEGORY(DRIVER, COMMON)
231 CATEGORY(FRONTEND, DRIVER)
232 CATEGORY(SERIALIZATION, FRONTEND)
233 CATEGORY(LEX, SERIALIZATION)
234 CATEGORY(PARSE, LEX)
235 CATEGORY(AST, PARSE)
236 CATEGORY(COMMENT, AST)
237 CATEGORY(CROSSTU, COMMENT)
238 CATEGORY(SEMA, CROSSTU)
239 CATEGORY(ANALYSIS, SEMA)
240 CATEGORY(REFACTORING, ANALYSIS)
241 #undef CATEGORY
242 
243  // Avoid out of bounds reads.
244  if (ID + Offset >= StaticDiagInfoSize)
245  return nullptr;
246 
248 
249  const StaticDiagInfoRec *Found = &StaticDiagInfo[ID + Offset];
250  // If the diag id doesn't match we found a different diag, abort. This can
251  // happen when this function is called with an ID that points into a hole in
252  // the diagID space.
253  if (Found->DiagID != DiagID)
254  return nullptr;
255  return Found;
256 }
257 
258 static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID) {
260  diag::Severity::Fatal, /*IsUser=*/false, /*IsPragma=*/false);
261 
262  if (const StaticDiagInfoRec *StaticInfo = GetDiagInfo(DiagID)) {
263  Info.setSeverity((diag::Severity)StaticInfo->DefaultSeverity);
264 
265  if (StaticInfo->WarnNoWerror) {
266  assert(Info.getSeverity() == diag::Severity::Warning &&
267  "Unexpected mapping with no-Werror bit!");
268  Info.setNoWarningAsError(true);
269  }
270  }
271 
272  return Info;
273 }
274 
275 /// getCategoryNumberForDiag - Return the category number that a specified
276 /// DiagID belongs to, or 0 if no category.
277 unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
278  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
279  return Info->Category;
280  return 0;
281 }
282 
283 namespace {
284  // The diagnostic category names.
285  struct StaticDiagCategoryRec {
286  const char *NameStr;
287  uint8_t NameLen;
288 
289  StringRef getName() const {
290  return StringRef(NameStr, NameLen);
291  }
292  };
293 }
294 
295 // Unfortunately, the split between DiagnosticIDs and Diagnostic is not
296 // particularly clean, but for now we just implement this method here so we can
297 // access GetDefaultDiagMapping.
299 DiagnosticsEngine::DiagState::getOrAddMapping(diag::kind Diag) {
300  std::pair<iterator, bool> Result =
301  DiagMap.insert(std::make_pair(Diag, DiagnosticMapping()));
302 
303  // Initialize the entry if we added it.
304  if (Result.second)
305  Result.first->second = GetDefaultDiagMapping(Diag);
306 
307  return Result.first->second;
308 }
309 
310 static const StaticDiagCategoryRec CategoryNameTable[] = {
311 #define GET_CATEGORY_TABLE
312 #define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
313 #include "clang/Basic/DiagnosticGroups.inc"
314 #undef GET_CATEGORY_TABLE
315  { nullptr, 0 }
316 };
317 
318 /// getNumberOfCategories - Return the number of categories
320  return llvm::array_lengthof(CategoryNameTable) - 1;
321 }
322 
323 /// getCategoryNameFromID - Given a category ID, return the name of the
324 /// category, an empty string if CategoryID is zero, or null if CategoryID is
325 /// invalid.
326 StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
327  if (CategoryID >= getNumberOfCategories())
328  return StringRef();
329  return CategoryNameTable[CategoryID].getName();
330 }
331 
332 
333 
336  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
337  return static_cast<DiagnosticIDs::SFINAEResponse>(Info->SFINAE);
338  return SFINAE_Report;
339 }
340 
341 bool DiagnosticIDs::isDeferrable(unsigned DiagID) {
342  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
343  return Info->Deferrable;
344  return false;
345 }
346 
347 /// getBuiltinDiagClass - Return the class field of the diagnostic.
348 ///
349 static unsigned getBuiltinDiagClass(unsigned DiagID) {
350  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
351  return Info->Class;
352  return ~0U;
353 }
354 
355 //===----------------------------------------------------------------------===//
356 // Custom Diagnostic information
357 //===----------------------------------------------------------------------===//
358 
359 namespace clang {
360  namespace diag {
362  typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
363  std::vector<DiagDesc> DiagInfo;
364  std::map<DiagDesc, unsigned> DiagIDs;
365  public:
366 
367  /// getDescription - Return the description of the specified custom
368  /// diagnostic.
369  StringRef getDescription(unsigned DiagID) const {
370  assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
371  "Invalid diagnostic ID");
372  return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
373  }
374 
375  /// getLevel - Return the level of the specified custom diagnostic.
376  DiagnosticIDs::Level getLevel(unsigned DiagID) const {
377  assert(DiagID - DIAG_UPPER_LIMIT < DiagInfo.size() &&
378  "Invalid diagnostic ID");
379  return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
380  }
381 
382  unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
383  DiagnosticIDs &Diags) {
384  DiagDesc D(L, std::string(Message));
385  // Check to see if it already exists.
386  std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
387  if (I != DiagIDs.end() && I->first == D)
388  return I->second;
389 
390  // If not, assign a new ID.
391  unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
392  DiagIDs.insert(std::make_pair(D, ID));
393  DiagInfo.push_back(D);
394  return ID;
395  }
396  };
397 
398  } // end diag namespace
399 } // end clang namespace
400 
401 
402 //===----------------------------------------------------------------------===//
403 // Common Diagnostic implementation
404 //===----------------------------------------------------------------------===//
405 
407 
409 
410 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
411 /// and level. If this is the first request for this diagnostic, it is
412 /// registered and created, otherwise the existing ID is returned.
413 ///
414 /// \param FormatString A fixed diagnostic format string that will be hashed and
415 /// mapped to a unique DiagID.
416 unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef FormatString) {
417  if (!CustomDiagInfo)
418  CustomDiagInfo.reset(new diag::CustomDiagInfo());
419  return CustomDiagInfo->getOrCreateDiagID(L, FormatString, *this);
420 }
421 
422 
423 /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
424 /// level of the specified diagnostic ID is a Warning or Extension.
425 /// This only works on builtin diagnostics, not custom ones, and is not legal to
426 /// call on NOTEs.
428  return DiagID < diag::DIAG_UPPER_LIMIT &&
429  getBuiltinDiagClass(DiagID) != CLASS_ERROR;
430 }
431 
432 /// Determine whether the given built-in diagnostic ID is a
433 /// Note.
434 bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
435  return DiagID < diag::DIAG_UPPER_LIMIT &&
436  getBuiltinDiagClass(DiagID) == CLASS_NOTE;
437 }
438 
439 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
440 /// ID is for an extension of some sort. This also returns EnabledByDefault,
441 /// which is set to indicate whether the diagnostic is ignored by default (in
442 /// which case -pedantic enables it) or treated as a warning/error by default.
443 ///
445  bool &EnabledByDefault) {
446  if (DiagID >= diag::DIAG_UPPER_LIMIT ||
447  getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
448  return false;
449 
450  EnabledByDefault =
452  return true;
453 }
454 
456  if (DiagID >= diag::DIAG_UPPER_LIMIT)
457  return false;
458 
460 }
461 
462 /// getDescription - Given a diagnostic ID, return a description of the
463 /// issue.
464 StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
465  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
466  return Info->getDescription();
467  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
468  return CustomDiagInfo->getDescription(DiagID);
469 }
470 
472  switch (SV) {
474  return DiagnosticIDs::Ignored;
476  return DiagnosticIDs::Remark;
478  return DiagnosticIDs::Warning;
480  return DiagnosticIDs::Error;
482  return DiagnosticIDs::Fatal;
483  }
484  llvm_unreachable("unexpected severity");
485 }
486 
487 /// getDiagnosticLevel - Based on the way the client configured the
488 /// DiagnosticsEngine object, classify the specified diagnostic ID into a Level,
489 /// by consumable the DiagnosticClient.
491 DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
492  const DiagnosticsEngine &Diag) const {
493  // Handle custom diagnostics, which cannot be mapped.
494  if (DiagID >= diag::DIAG_UPPER_LIMIT) {
495  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
496  return CustomDiagInfo->getLevel(DiagID);
497  }
498 
499  unsigned DiagClass = getBuiltinDiagClass(DiagID);
500  if (DiagClass == CLASS_NOTE) return DiagnosticIDs::Note;
501  return toLevel(getDiagnosticSeverity(DiagID, Loc, Diag));
502 }
503 
504 /// Based on the way the client configured the Diagnostic
505 /// object, classify the specified diagnostic ID into a Level, consumable by
506 /// the DiagnosticClient.
507 ///
508 /// \param Loc The source location we are interested in finding out the
509 /// diagnostic state. Can be null in order to query the latest state.
511 DiagnosticIDs::getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc,
512  const DiagnosticsEngine &Diag) const {
513  assert(getBuiltinDiagClass(DiagID) != CLASS_NOTE);
514 
515  // Specific non-error diagnostics may be mapped to various levels from ignored
516  // to error. Errors can only be mapped to fatal.
518 
519  // Get the mapping information, or compute it lazily.
520  DiagnosticsEngine::DiagState *State = Diag.GetDiagStateForLoc(Loc);
521  DiagnosticMapping &Mapping = State->getOrAddMapping((diag::kind)DiagID);
522 
523  // TODO: Can a null severity really get here?
524  if (Mapping.getSeverity() != diag::Severity())
525  Result = Mapping.getSeverity();
526 
527  // Upgrade ignored diagnostics if -Weverything is enabled.
528  if (State->EnableAllWarnings && Result == diag::Severity::Ignored &&
529  !Mapping.isUser() && getBuiltinDiagClass(DiagID) != CLASS_REMARK)
530  Result = diag::Severity::Warning;
531 
532  // Ignore -pedantic diagnostics inside __extension__ blocks.
533  // (The diagnostics controlled by -pedantic are the extension diagnostics
534  // that are not enabled by default.)
535  bool EnabledByDefault = false;
536  bool IsExtensionDiag = isBuiltinExtensionDiag(DiagID, EnabledByDefault);
537  if (Diag.AllExtensionsSilenced && IsExtensionDiag && !EnabledByDefault)
539 
540  // For extension diagnostics that haven't been explicitly mapped, check if we
541  // should upgrade the diagnostic.
542  if (IsExtensionDiag && !Mapping.isUser())
543  Result = std::max(Result, State->ExtBehavior);
544 
545  // At this point, ignored errors can no longer be upgraded.
546  if (Result == diag::Severity::Ignored)
547  return Result;
548 
549  // Honor -w: this disables all messages which which are not Error/Fatal by
550  // default (disregarding attempts to upgrade severity from Warning to Error),
551  // as well as disabling all messages which are currently mapped to Warning
552  // (whether by default or downgraded from Error via e.g. -Wno-error or #pragma
553  // diagnostic.)
554  if (State->IgnoreAllWarnings) {
555  if (Result == diag::Severity::Warning ||
556  (Result >= diag::Severity::Error &&
559  }
560 
561  // If -Werror is enabled, map warnings to errors unless explicitly disabled.
562  if (Result == diag::Severity::Warning) {
563  if (State->WarningsAsErrors && !Mapping.hasNoWarningAsError())
564  Result = diag::Severity::Error;
565  }
566 
567  // If -Wfatal-errors is enabled, map errors to fatal unless explicitly
568  // disabled.
569  if (Result == diag::Severity::Error) {
570  if (State->ErrorsAsFatal && !Mapping.hasNoErrorAsFatal())
571  Result = diag::Severity::Fatal;
572  }
573 
574  // If explicitly requested, map fatal errors to errors.
575  if (Result == diag::Severity::Fatal &&
576  Diag.CurDiagID != diag::fatal_too_many_errors && Diag.FatalsAsError)
577  Result = diag::Severity::Error;
578 
579  // Custom diagnostics always are emitted in system headers.
580  bool ShowInSystemHeader =
581  !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemHeader;
582 
583  // If we are in a system header, we ignore it. We look at the diagnostic class
584  // because we also want to ignore extensions and warnings in -Werror and
585  // -pedantic-errors modes, which *map* warnings/extensions to errors.
586  if (State->SuppressSystemWarnings && !ShowInSystemHeader && Loc.isValid() &&
587  Diag.getSourceManager().isInSystemHeader(
588  Diag.getSourceManager().getExpansionLoc(Loc)))
590 
591  // We also ignore warnings due to system macros
592  bool ShowInSystemMacro =
593  !GetDiagInfo(DiagID) || GetDiagInfo(DiagID)->WarnShowInSystemMacro;
594  if (State->SuppressSystemWarnings && !ShowInSystemMacro && Loc.isValid() &&
595  Diag.getSourceManager().isInSystemMacro(Loc))
597 
598  return Result;
599 }
600 
601 #define GET_DIAG_ARRAYS
602 #include "clang/Basic/DiagnosticGroups.inc"
603 #undef GET_DIAG_ARRAYS
604 
605 namespace {
606  struct WarningOption {
607  uint16_t NameOffset;
608  uint16_t Members;
609  uint16_t SubGroups;
610 
611  // String is stored with a pascal-style length byte.
612  StringRef getName() const {
613  return StringRef(DiagGroupNames + NameOffset + 1,
614  DiagGroupNames[NameOffset]);
615  }
616  };
617 }
618 
619 // Second the table of options, sorted by name for fast binary lookup.
620 static const WarningOption OptionTable[] = {
621 #define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups) \
622  {FlagNameOffset, Members, SubGroups},
623 #include "clang/Basic/DiagnosticGroups.inc"
624 #undef DIAG_ENTRY
625 };
626 
628  return OptionTable[static_cast<int>(Group)].getName();
629 }
630 
633  const auto *Found = llvm::partition_point(
634  OptionTable, [=](const WarningOption &O) { return O.getName() < Name; });
635  if (Found == std::end(OptionTable) || Found->getName() != Name)
636  return llvm::None;
637  return static_cast<diag::Group>(Found - OptionTable);
638 }
639 
641  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
642  return static_cast<diag::Group>(Info->getOptionGroupIndex());
643  return llvm::None;
644 }
645 
646 /// getWarningOptionForDiag - Return the lowest-level warning option that
647 /// enables the specified diagnostic. If there is no -Wfoo flag that controls
648 /// the diagnostic, this returns null.
649 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
650  if (auto G = getGroupForDiag(DiagID))
651  return getWarningOptionForGroup(*G);
652  return StringRef();
653 }
654 
655 std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() {
656  std::vector<std::string> Res;
657  for (size_t I = 1; DiagGroupNames[I] != '\0';) {
658  std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
659  I += DiagGroupNames[I] + 1;
660  Res.push_back("-W" + Diag);
661  Res.push_back("-Wno-" + Diag);
662  }
663 
664  return Res;
665 }
666 
667 /// Return \c true if any diagnostics were found in this group, even if they
668 /// were filtered out due to having the wrong flavor.
670  const WarningOption *Group,
672  // An empty group is considered to be a warning group: we have empty groups
673  // for GCC compatibility, and GCC does not have remarks.
674  if (!Group->Members && !Group->SubGroups)
675  return Flavor == diag::Flavor::Remark;
676 
677  bool NotFound = true;
678 
679  // Add the members of the option diagnostic set.
680  const int16_t *Member = DiagArrays + Group->Members;
681  for (; *Member != -1; ++Member) {
682  if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
683  NotFound = false;
684  Diags.push_back(*Member);
685  }
686  }
687 
688  // Add the members of the subgroups.
689  const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
690  for (; *SubGroups != (int16_t)-1; ++SubGroups)
691  NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
692  Diags);
693 
694  return NotFound;
695 }
696 
697 bool
699  SmallVectorImpl<diag::kind> &Diags) const {
702  Flavor, &OptionTable[static_cast<unsigned>(*G)], Diags);
703  return true;
704 }
705 
707  std::vector<diag::kind> &Diags) {
708  for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
709  if (StaticDiagInfo[i].getFlavor() == Flavor)
710  Diags.push_back(StaticDiagInfo[i].DiagID);
711 }
712 
714  StringRef Group) {
715  StringRef Best;
716  unsigned BestDistance = Group.size() + 1; // Maximum threshold.
717  for (const WarningOption &O : OptionTable) {
718  // Don't suggest ignored warning flags.
719  if (!O.Members && !O.SubGroups)
720  continue;
721 
722  unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
723  if (Distance > BestDistance)
724  continue;
725 
726  // Don't suggest groups that are not of this kind.
728  if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty())
729  continue;
730 
731  if (Distance == BestDistance) {
732  // Two matches with the same distance, don't prefer one over the other.
733  Best = "";
734  } else if (Distance < BestDistance) {
735  // This is a better match.
736  Best = O.getName();
737  BestDistance = Distance;
738  }
739  }
740 
741  return Best;
742 }
743 
744 /// ProcessDiag - This is the method used to report a diagnostic that is
745 /// finally fully formed.
746 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
747  Diagnostic Info(&Diag);
748 
749  assert(Diag.getClient() && "DiagnosticClient not set!");
750 
751  // Figure out the diagnostic level of this message.
752  unsigned DiagID = Info.getID();
753  DiagnosticIDs::Level DiagLevel
754  = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
755 
756  // Update counts for DiagnosticErrorTrap even if a fatal error occurred
757  // or diagnostics are suppressed.
758  if (DiagLevel >= DiagnosticIDs::Error) {
759  ++Diag.TrapNumErrorsOccurred;
760  if (isUnrecoverable(DiagID))
761  ++Diag.TrapNumUnrecoverableErrorsOccurred;
762  }
763 
764  if (Diag.SuppressAllDiagnostics)
765  return false;
766 
767  if (DiagLevel != DiagnosticIDs::Note) {
768  // Record that a fatal error occurred only when we see a second
769  // non-note diagnostic. This allows notes to be attached to the
770  // fatal error, but suppresses any diagnostics that follow those
771  // notes.
772  if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
773  Diag.FatalErrorOccurred = true;
774 
775  Diag.LastDiagLevel = DiagLevel;
776  }
777 
778  // If a fatal error has already been emitted, silence all subsequent
779  // diagnostics.
780  if (Diag.FatalErrorOccurred) {
781  if (DiagLevel >= DiagnosticIDs::Error &&
782  Diag.Client->IncludeInDiagnosticCounts()) {
783  ++Diag.NumErrors;
784  }
785 
786  return false;
787  }
788 
789  // If the client doesn't care about this message, don't issue it. If this is
790  // a note and the last real diagnostic was ignored, ignore it too.
791  if (DiagLevel == DiagnosticIDs::Ignored ||
792  (DiagLevel == DiagnosticIDs::Note &&
793  Diag.LastDiagLevel == DiagnosticIDs::Ignored))
794  return false;
795 
796  if (DiagLevel >= DiagnosticIDs::Error) {
797  if (isUnrecoverable(DiagID))
798  Diag.UnrecoverableErrorOccurred = true;
799 
800  // Warnings which have been upgraded to errors do not prevent compilation.
801  if (isDefaultMappingAsError(DiagID))
802  Diag.UncompilableErrorOccurred = true;
803 
804  Diag.ErrorOccurred = true;
805  if (Diag.Client->IncludeInDiagnosticCounts()) {
806  ++Diag.NumErrors;
807  }
808 
809  // If we've emitted a lot of errors, emit a fatal error instead of it to
810  // stop a flood of bogus errors.
811  if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
812  DiagLevel == DiagnosticIDs::Error) {
813  Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
814  return false;
815  }
816  }
817 
818  // Make sure we set FatalErrorOccurred to ensure that the notes from the
819  // diagnostic that caused `fatal_too_many_errors` won't be emitted.
820  if (Diag.CurDiagID == diag::fatal_too_many_errors)
821  Diag.FatalErrorOccurred = true;
822  // Finally, report it.
823  EmitDiag(Diag, DiagLevel);
824  return true;
825 }
826 
827 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
828  Diagnostic Info(&Diag);
829  assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
830 
831  Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
832  if (Diag.Client->IncludeInDiagnosticCounts()) {
833  if (DiagLevel == DiagnosticIDs::Warning)
834  ++Diag.NumWarnings;
835  }
836 
837  Diag.CurDiagID = ~0U;
838 }
839 
840 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
841  if (DiagID >= diag::DIAG_UPPER_LIMIT) {
842  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
843  // Custom diagnostics.
844  return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
845  }
846 
847  // Only errors may be unrecoverable.
848  if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
849  return false;
850 
851  if (DiagID == diag::err_unavailable ||
852  DiagID == diag::err_unavailable_message)
853  return false;
854 
855  // Currently we consider all ARC errors as recoverable.
856  if (isARCDiagnostic(DiagID))
857  return false;
858 
859  return true;
860 }
861 
862 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
863  unsigned cat = getCategoryNumberForDiag(DiagID);
864  return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
865 }
clang::DiagnosticIDs::isDeferrable
static bool isDeferrable(unsigned DiagID)
Whether the diagnostic message can be deferred.
Definition: DiagnosticIDs.cpp:341
clang::DiagnosticsEngine::Level
Level
The level of the diagnostic, after it has been through mapping.
Definition: Diagnostic.h:195
clang::diag::Severity
Severity
Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs to either Ignore (nothing),...
Definition: DiagnosticIDs.h:82
max
__DEVICE__ int max(int __a, int __b)
Definition: __clang_cuda_math.h:196
clang::DiagnosticIDs::getAllDiagnostics
static void getAllDiagnostics(diag::Flavor Flavor, std::vector< diag::kind > &Diags)
Get the set of all diagnostic IDs.
Definition: DiagnosticIDs.cpp:706
clang::diag::Severity::Error
@ Error
Present this diagnostic as an error.
clang::index::SymbolKind::Class
@ Class
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::DiagnosticIDs::getDiagnosticFlags
static std::vector< std::string > getDiagnosticFlags()
Get the string of all diagnostic flags.
Definition: DiagnosticIDs.cpp:655
Diag
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.
Definition: LiteralSupport.cpp:78
llvm::SmallVector
Definition: LLVM.h:38
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:86
OptionTable
static const WarningOption OptionTable[]
Definition: DiagnosticIDs.cpp:620
clang::DiagnosticIDs::getCustomDiagID
unsigned getCustomDiagID(Level L, StringRef FormatString)
Return an ID for a diagnostic with the specified format string and level.
Definition: DiagnosticIDs.cpp:416
clang::diag::DIAG_START_COMMON
@ DIAG_START_COMMON
Definition: DiagnosticIDs.h:47
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:192
clang::transformer::cat
Stencil cat(Ts &&... Parts)
Concatenates 0+ stencil pieces into a single stencil.
Definition: Stencil.h:64
clang::diag::Severity::Remark
@ Remark
Present this diagnostic as a remark.
VALIDATE_DIAG_SIZE
#define VALIDATE_DIAG_SIZE(NAME)
Definition: DiagnosticIDs.cpp:147
clang::DiagnosticMapping::hasNoWarningAsError
bool hasNoWarningAsError() const
Definition: DiagnosticIDs.h:133
clang::diag::CustomDiagInfo::getLevel
DiagnosticIDs::Level getLevel(unsigned DiagID) const
getLevel - Return the level of the specified custom diagnostic.
Definition: DiagnosticIDs.cpp:376
llvm::Optional
Definition: LLVM.h:40
clang::DiagnosticIDs::Level
Level
The level of the diagnostic, after it has been through mapping.
Definition: DiagnosticIDs.h:169
SourceManager.h
DiagnosticIDs.h
clang::diag::Group
Group
Definition: DiagnosticCategories.h:23
clang::DiagnosticIDs::isBuiltinNote
static bool isBuiltinNote(unsigned DiagID)
Determine whether the given built-in diagnostic ID is a Note.
Definition: DiagnosticIDs.cpp:434
toLevel
static DiagnosticIDs::Level toLevel(diag::Severity SV)
Definition: DiagnosticIDs.cpp:471
clang::DiagnosticIDs::getDiagnosticsInGroup
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.
Definition: DiagnosticIDs.cpp:698
StaticDiagInfoSize
static const unsigned StaticDiagInfoSize
Definition: DiagnosticIDs.cpp:205
Offset
unsigned Offset
Definition: Format.cpp:2553
clang::DiagnosticMapping::hasNoErrorAsFatal
bool hasNoErrorAsFatal() const
Definition: DiagnosticIDs.h:136
clang::Diagnostic
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1560
U
clang::diag::Severity::Ignored
@ Ignored
Do not present this diagnostic, ignore it.
clang::DiagnosticIDs::SFINAEResponse
SFINAEResponse
Enumeration describing how the emission of a diagnostic should be treated when it occurs during C++ t...
Definition: DiagnosticIDs.h:264
clang::DiagnosticIDs::getWarningOptionForGroup
static StringRef getWarningOptionForGroup(diag::Group)
Given a group ID, returns the flag that toggles the group.
Definition: DiagnosticIDs.cpp:627
clang::diag::Flavor::WarningOrError
@ WarningOrError
A diagnostic that indicates a problem or potential problem.
getDiagnosticsInGroup
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...
Definition: DiagnosticIDs.cpp:669
AllDiagnostics.h
clang::diag::Severity::Fatal
@ Fatal
Present this diagnostic as a fatal error.
clang::DiagnosticIDs::isDefaultMappingAsError
static bool isDefaultMappingAsError(unsigned DiagID)
Return true if the specified diagnostic is mapped to errors by default.
Definition: DiagnosticIDs.cpp:455
clang::DiagnosticIDs::getDescription
StringRef getDescription(unsigned DiagID) const
Given a diagnostic ID, return a description of the issue.
Definition: DiagnosticIDs.cpp:464
clang::DeclaratorContext::Member
@ Member
clang::DiagnosticIDs::isARCDiagnostic
static bool isARCDiagnostic(unsigned DiagID)
Return true if a given diagnostic falls into an ARC diagnostic category.
Definition: DiagnosticIDs.cpp:862
clang::DiagnosticMapping
Definition: DiagnosticIDs.h:101
clang::DiagnosticIDs::getDiagnosticSFINAEResponse
static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID)
Determines whether the given built-in diagnostic ID is for an error that is suppressed if it occurs d...
Definition: DiagnosticIDs.cpp:335
clang::DiagnosticIDs::Note
@ Note
Definition: DiagnosticIDs.h:170
Category
int Category
Definition: Format.cpp:2554
clang::diag::DIAG_UPPER_LIMIT
@ DIAG_UPPER_LIMIT
Definition: DiagnosticIDs.h:59
getName
static std::string getName(const CallEvent &Call)
Definition: ReturnValueChecker.cpp:61
COMMENT
#define COMMENT(CLASS, PARENT)
Definition: Comment.h:188
clang::diag::CustomDiagInfo::getDescription
StringRef getDescription(unsigned DiagID) const
getDescription - Return the description of the specified custom diagnostic.
Definition: DiagnosticIDs.cpp:369
ANALYSIS
#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)
Definition: AnalyzerOptions.h:38
CategoryNameTable
static const StaticDiagCategoryRec CategoryNameTable[]
Definition: DiagnosticIDs.cpp:310
clang::DiagnosticIDs::getCategoryNumberForDiag
static unsigned getCategoryNumberForDiag(unsigned DiagID)
Return the category number that a specified DiagID belongs to, or 0 if no category.
Definition: DiagnosticIDs.cpp:277
clang::DiagnosticIDs::DiagnosticIDs
DiagnosticIDs()
Definition: DiagnosticIDs.cpp:406
clang::diag::Severity::Warning
@ Warning
Present this diagnostic as a warning.
clang::DiagnosticMapping::getSeverity
diag::Severity getSeverity() const
Definition: DiagnosticIDs.h:122
GetDefaultDiagMapping
static DiagnosticMapping GetDefaultDiagMapping(unsigned DiagID)
Definition: DiagnosticIDs.cpp:258
clang::DiagnosticIDs::getGroupForWarningOption
static llvm::Optional< diag::Group > getGroupForWarningOption(StringRef)
Given a group ID, returns the flag that toggles the group.
Definition: DiagnosticIDs.cpp:632
clang::DiagnosticIDs::getCategoryNameFromID
static StringRef getCategoryNameFromID(unsigned CategoryID)
Given a category ID, return the name of the category.
Definition: DiagnosticIDs.cpp:326
clang::diag::CustomDiagInfo
Definition: DiagnosticIDs.cpp:361
clang::diag::CustomDiagInfo::getOrCreateDiagID
unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message, DiagnosticIDs &Diags)
Definition: DiagnosticIDs.cpp:382
clang::DiagnosticIDs
Used for handling and querying diagnostic IDs.
Definition: DiagnosticIDs.h:166
CATEGORY
#define CATEGORY(NAME, PREV)
State
LineState State
Definition: UnwrappedLineFormatter.cpp:1090
DiagnosticCategories.h
clang::diag::Flavor
Flavor
Flavors of diagnostics we can emit.
Definition: DiagnosticIDs.h:93
clang::DiagnosticMapping::setSeverity
void setSeverity(diag::Severity Value)
Definition: DiagnosticIDs.h:123
clang::DiagnosticIDs::Error
@ Error
Definition: DiagnosticIDs.h:170
clang::DiagnosticIDs::Remark
@ Remark
Definition: DiagnosticIDs.h:170
clang::diag::Flavor::Remark
@ Remark
A diagnostic that indicates normal progress through compilation.
clang::DiagnosticIDs::Warning
@ Warning
Definition: DiagnosticIDs.h:170
clang::Builtin::ID
ID
Definition: Builtins.h:51
clang
Definition: CalledOnceCheck.h:17
clang::DiagnosticIDs::Ignored
@ Ignored
Definition: DiagnosticIDs.h:170
getBuiltinDiagClass
static unsigned getBuiltinDiagClass(unsigned DiagID)
getBuiltinDiagClass - Return the class field of the diagnostic.
Definition: DiagnosticIDs.cpp:349
clang::DiagnosticIDs::~DiagnosticIDs
~DiagnosticIDs()
Definition: DiagnosticIDs.cpp:408
clang::prec::Level
Level
Definition: OperatorPrecedence.h:26
clang::operator<
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
Definition: DeclarationName.h:549
clang::SourceLocation::isValid
bool isValid() const
Return true if this is a valid SourceLocation object.
Definition: SourceLocation.h:110
clang::DiagnosticIDs::getNumberOfCategories
static unsigned getNumberOfCategories()
Return the number of diagnostic categories.
Definition: DiagnosticIDs.cpp:319
unsigned
clang::DiagnosticMapping::Make
static DiagnosticMapping Make(diag::Severity Severity, bool IsUser, bool IsPragma)
Definition: DiagnosticIDs.h:110
clang::DiagnosticMapping::isUser
bool isUser() const
Definition: DiagnosticIDs.h:125
clang::DiagnosticIDs::getNearestOption
static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group)
Get the diagnostic option with the closest edit distance to the given group name.
Definition: DiagnosticIDs.cpp:713
clang::DiagnosticIDs::isBuiltinWarningOrExtension
static bool isBuiltinWarningOrExtension(unsigned DiagID)
Return true if the unmapped diagnostic levelof the specified diagnostic ID is a Warning or Extension.
Definition: DiagnosticIDs.cpp:427
clang::DiagnosticIDs::isBuiltinExtensionDiag
static bool isBuiltinExtensionDiag(unsigned DiagID)
Determine whether the given built-in diagnostic ID is for an extension of some sort.
Definition: DiagnosticIDs.h:215
llvm::SmallVectorImpl
Definition: Randstruct.h:18
GetDiagInfo
static const StaticDiagInfoRec * GetDiagInfo(unsigned DiagID)
GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, or null if the ID is inval...
Definition: DiagnosticIDs.cpp:209
clang::DiagnosticMapping::setNoWarningAsError
void setNoWarningAsError(bool Value)
Definition: DiagnosticIDs.h:134
clang::DiagnosticIDs::getWarningOptionForDiag
static StringRef getWarningOptionForDiag(unsigned DiagID)
Return the lowest-level warning option that enables the specified diagnostic.
Definition: DiagnosticIDs.cpp:649
clang::DiagnosticIDs::getGroupForDiag
static llvm::Optional< diag::Group > getGroupForDiag(unsigned DiagID)
Return the lowest-level group that contains the specified diagnostic.
Definition: DiagnosticIDs.cpp:640
clang::DiagnosticIDs::SFINAE_Report
@ SFINAE_Report
The diagnostic should be reported.
Definition: DiagnosticIDs.h:281
clang::DiagnosticIDs::Fatal
@ Fatal
Definition: DiagnosticIDs.h:170