clang  13.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 GET_DIAG_TABLE
613 #include "clang/Basic/DiagnosticGroups.inc"
614 #undef GET_DIAG_TABLE
615 };
616 
617 /// getWarningOptionForDiag - Return the lowest-level warning option that
618 /// enables the specified diagnostic. If there is no -Wfoo flag that controls
619 /// the diagnostic, this returns null.
620 StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
621  if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
622  return OptionTable[Info->getOptionGroupIndex()].getName();
623  return StringRef();
624 }
625 
626 std::vector<std::string> DiagnosticIDs::getDiagnosticFlags() {
627  std::vector<std::string> Res;
628  for (size_t I = 1; DiagGroupNames[I] != '\0';) {
629  std::string Diag(DiagGroupNames + I + 1, DiagGroupNames[I]);
630  I += DiagGroupNames[I] + 1;
631  Res.push_back("-W" + Diag);
632  Res.push_back("-Wno-" + Diag);
633  }
634 
635  return Res;
636 }
637 
638 /// Return \c true if any diagnostics were found in this group, even if they
639 /// were filtered out due to having the wrong flavor.
641  const WarningOption *Group,
643  // An empty group is considered to be a warning group: we have empty groups
644  // for GCC compatibility, and GCC does not have remarks.
645  if (!Group->Members && !Group->SubGroups)
646  return Flavor == diag::Flavor::Remark;
647 
648  bool NotFound = true;
649 
650  // Add the members of the option diagnostic set.
651  const int16_t *Member = DiagArrays + Group->Members;
652  for (; *Member != -1; ++Member) {
653  if (GetDiagInfo(*Member)->getFlavor() == Flavor) {
654  NotFound = false;
655  Diags.push_back(*Member);
656  }
657  }
658 
659  // Add the members of the subgroups.
660  const int16_t *SubGroups = DiagSubGroups + Group->SubGroups;
661  for (; *SubGroups != (int16_t)-1; ++SubGroups)
662  NotFound &= getDiagnosticsInGroup(Flavor, &OptionTable[(short)*SubGroups],
663  Diags);
664 
665  return NotFound;
666 }
667 
668 bool
670  SmallVectorImpl<diag::kind> &Diags) const {
671  auto Found = llvm::partition_point(
672  OptionTable, [=](const WarningOption &O) { return O.getName() < Group; });
673  if (Found == std::end(OptionTable) || Found->getName() != Group)
674  return true; // Option not found.
675 
676  return ::getDiagnosticsInGroup(Flavor, Found, Diags);
677 }
678 
680  std::vector<diag::kind> &Diags) {
681  for (unsigned i = 0; i != StaticDiagInfoSize; ++i)
682  if (StaticDiagInfo[i].getFlavor() == Flavor)
683  Diags.push_back(StaticDiagInfo[i].DiagID);
684 }
685 
687  StringRef Group) {
688  StringRef Best;
689  unsigned BestDistance = Group.size() + 1; // Sanity threshold.
690  for (const WarningOption &O : OptionTable) {
691  // Don't suggest ignored warning flags.
692  if (!O.Members && !O.SubGroups)
693  continue;
694 
695  unsigned Distance = O.getName().edit_distance(Group, true, BestDistance);
696  if (Distance > BestDistance)
697  continue;
698 
699  // Don't suggest groups that are not of this kind.
701  if (::getDiagnosticsInGroup(Flavor, &O, Diags) || Diags.empty())
702  continue;
703 
704  if (Distance == BestDistance) {
705  // Two matches with the same distance, don't prefer one over the other.
706  Best = "";
707  } else if (Distance < BestDistance) {
708  // This is a better match.
709  Best = O.getName();
710  BestDistance = Distance;
711  }
712  }
713 
714  return Best;
715 }
716 
717 /// ProcessDiag - This is the method used to report a diagnostic that is
718 /// finally fully formed.
719 bool DiagnosticIDs::ProcessDiag(DiagnosticsEngine &Diag) const {
720  Diagnostic Info(&Diag);
721 
722  assert(Diag.getClient() && "DiagnosticClient not set!");
723 
724  // Figure out the diagnostic level of this message.
725  unsigned DiagID = Info.getID();
726  DiagnosticIDs::Level DiagLevel
727  = getDiagnosticLevel(DiagID, Info.getLocation(), Diag);
728 
729  // Update counts for DiagnosticErrorTrap even if a fatal error occurred
730  // or diagnostics are suppressed.
731  if (DiagLevel >= DiagnosticIDs::Error) {
732  ++Diag.TrapNumErrorsOccurred;
733  if (isUnrecoverable(DiagID))
734  ++Diag.TrapNumUnrecoverableErrorsOccurred;
735  }
736 
737  if (Diag.SuppressAllDiagnostics)
738  return false;
739 
740  if (DiagLevel != DiagnosticIDs::Note) {
741  // Record that a fatal error occurred only when we see a second
742  // non-note diagnostic. This allows notes to be attached to the
743  // fatal error, but suppresses any diagnostics that follow those
744  // notes.
745  if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
746  Diag.FatalErrorOccurred = true;
747 
748  Diag.LastDiagLevel = DiagLevel;
749  }
750 
751  // If a fatal error has already been emitted, silence all subsequent
752  // diagnostics.
753  if (Diag.FatalErrorOccurred) {
754  if (DiagLevel >= DiagnosticIDs::Error &&
755  Diag.Client->IncludeInDiagnosticCounts()) {
756  ++Diag.NumErrors;
757  }
758 
759  return false;
760  }
761 
762  // If the client doesn't care about this message, don't issue it. If this is
763  // a note and the last real diagnostic was ignored, ignore it too.
764  if (DiagLevel == DiagnosticIDs::Ignored ||
765  (DiagLevel == DiagnosticIDs::Note &&
766  Diag.LastDiagLevel == DiagnosticIDs::Ignored))
767  return false;
768 
769  if (DiagLevel >= DiagnosticIDs::Error) {
770  if (isUnrecoverable(DiagID))
771  Diag.UnrecoverableErrorOccurred = true;
772 
773  // Warnings which have been upgraded to errors do not prevent compilation.
774  if (isDefaultMappingAsError(DiagID))
775  Diag.UncompilableErrorOccurred = true;
776 
777  Diag.ErrorOccurred = true;
778  if (Diag.Client->IncludeInDiagnosticCounts()) {
779  ++Diag.NumErrors;
780  }
781 
782  // If we've emitted a lot of errors, emit a fatal error instead of it to
783  // stop a flood of bogus errors.
784  if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
785  DiagLevel == DiagnosticIDs::Error) {
786  Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
787  return false;
788  }
789  }
790 
791  // Make sure we set FatalErrorOccurred to ensure that the notes from the
792  // diagnostic that caused `fatal_too_many_errors` won't be emitted.
793  if (Diag.CurDiagID == diag::fatal_too_many_errors)
794  Diag.FatalErrorOccurred = true;
795  // Finally, report it.
796  EmitDiag(Diag, DiagLevel);
797  return true;
798 }
799 
800 void DiagnosticIDs::EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const {
801  Diagnostic Info(&Diag);
802  assert(DiagLevel != DiagnosticIDs::Ignored && "Cannot emit ignored diagnostics!");
803 
804  Diag.Client->HandleDiagnostic((DiagnosticsEngine::Level)DiagLevel, Info);
805  if (Diag.Client->IncludeInDiagnosticCounts()) {
806  if (DiagLevel == DiagnosticIDs::Warning)
807  ++Diag.NumWarnings;
808  }
809 
810  Diag.CurDiagID = ~0U;
811 }
812 
813 bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
814  if (DiagID >= diag::DIAG_UPPER_LIMIT) {
815  assert(CustomDiagInfo && "Invalid CustomDiagInfo");
816  // Custom diagnostics.
817  return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
818  }
819 
820  // Only errors may be unrecoverable.
821  if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
822  return false;
823 
824  if (DiagID == diag::err_unavailable ||
825  DiagID == diag::err_unavailable_message)
826  return false;
827 
828  // Currently we consider all ARC errors as recoverable.
829  if (isARCDiagnostic(DiagID))
830  return false;
831 
832  return true;
833 }
834 
835 bool DiagnosticIDs::isARCDiagnostic(unsigned DiagID) {
836  unsigned cat = getCategoryNumberForDiag(DiagID);
837  return DiagnosticIDs::getCategoryNameFromID(cat).startswith("ARC ");
838 }
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:80
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:679
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:626
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:131
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:167
SourceManager.h
DiagnosticIDs.h
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:669
StaticDiagInfoSize
static const unsigned StaticDiagInfoSize
Definition: DiagnosticIDs.cpp:203
Offset
unsigned Offset
Definition: Format.cpp:2227
clang::DiagnosticMapping::hasNoErrorAsFatal
bool hasNoErrorAsFatal() const
Definition: DiagnosticIDs.h:134
clang::Diagnostic
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
Definition: Diagnostic.h:1532
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:250
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:640
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:57
clang::DiagnosticIDs::isARCDiagnostic
static bool isARCDiagnostic(unsigned DiagID)
Return true if a given diagnostic falls into an ARC diagnostic category.
Definition: DiagnosticIDs.cpp:835
clang::DiagnosticMapping
Definition: DiagnosticIDs.h:99
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:168
Category
int Category
Definition: Format.cpp:2228
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:120
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:45
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:164
CATEGORY
#define CATEGORY(NAME, PREV)
State
LineState State
Definition: UnwrappedLineFormatter.cpp:985
DiagnosticCategories.h
clang::diag::Flavor
Flavor
Flavors of diagnostics we can emit.
Definition: DiagnosticIDs.h:91
clang::DiagnosticMapping::setSeverity
void setSeverity(diag::Severity Value)
Definition: DiagnosticIDs.h:121
clang::DiagnosticIDs::Error
@ Error
Definition: DiagnosticIDs.h:168
clang::DiagnosticIDs::Remark
@ Remark
Definition: DiagnosticIDs.h:168
clang::diag::Flavor::Remark
@ Remark
A diagnostic that indicates normal progress through compilation.
clang::DiagnosticIDs::Warning
@ Warning
Definition: DiagnosticIDs.h:168
clang::Builtin::ID
ID
Definition: Builtins.h:48
clang
Definition: CalledOnceCheck.h:17
clang::DiagnosticIDs::Ignored
@ Ignored
Definition: DiagnosticIDs.h:168
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:108
clang::DiagnosticMapping::isUser
bool isUser() const
Definition: DiagnosticIDs.h:123
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:686
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:213
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:132
clang::DiagnosticIDs::getWarningOptionForDiag
static StringRef getWarningOptionForDiag(unsigned DiagID)
Return the lowest-level warning option that enables the specified diagnostic.
Definition: DiagnosticIDs.cpp:620
clang::DiagnosticIDs::SFINAE_Report
@ SFINAE_Report
The diagnostic should be reported.
Definition: DiagnosticIDs.h:267
clang::DiagnosticIDs::Fatal
@ Fatal
Definition: DiagnosticIDs.h:168