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