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