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