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