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