blob: ace92aceb4673c55723ce2d5ad180dd4944b18a8 [file] [log] [blame]
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +00001//===--- 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/AST/ASTDiagnostic.h"
15#include "clang/Analysis/AnalysisDiagnostic.h"
16#include "clang/Basic/DiagnosticIDs.h"
John McCall923cd572011-06-15 21:46:43 +000017#include "clang/Basic/DiagnosticCategories.h"
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +000018#include "clang/Basic/SourceManager.h"
19#include "clang/Driver/DriverDiagnostic.h"
20#include "clang/Frontend/FrontendDiagnostic.h"
21#include "clang/Lex/LexDiagnostic.h"
22#include "clang/Parse/ParseDiagnostic.h"
23#include "clang/Sema/SemaDiagnostic.h"
24
25#include <map>
26using namespace clang;
27
28//===----------------------------------------------------------------------===//
29// Builtin Diagnostic information
30//===----------------------------------------------------------------------===//
31
32namespace {
33
34// Diagnostic classes.
35enum {
36 CLASS_NOTE = 0x01,
37 CLASS_WARNING = 0x02,
38 CLASS_EXTENSION = 0x03,
39 CLASS_ERROR = 0x04
40};
41
42struct StaticDiagInfoRec {
43 unsigned short DiagID;
44 unsigned Mapping : 3;
45 unsigned Class : 3;
Douglas Gregor418df342011-01-27 21:06:28 +000046 unsigned SFINAE : 1;
47 unsigned AccessControl : 1;
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +000048 unsigned Category : 5;
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +000049
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +000050 uint8_t NameLen;
51 uint8_t OptionGroupLen;
52
53 uint16_t DescriptionLen;
54 uint16_t BriefExplanationLen;
55 uint16_t FullExplanationLen;
56
57 const char *NameStr;
58 const char *OptionGroupStr;
59
60 const char *DescriptionStr;
61 const char *BriefExplanationStr;
62 const char *FullExplanationStr;
63
Chris Lattner5f9e2722011-07-23 10:55:15 +000064 StringRef getName() const {
65 return StringRef(NameStr, NameLen);
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +000066 }
Chris Lattner5f9e2722011-07-23 10:55:15 +000067 StringRef getOptionGroup() const {
68 return StringRef(OptionGroupStr, OptionGroupLen);
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +000069 }
70
Chris Lattner5f9e2722011-07-23 10:55:15 +000071 StringRef getDescription() const {
72 return StringRef(DescriptionStr, DescriptionLen);
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +000073 }
Chris Lattner5f9e2722011-07-23 10:55:15 +000074 StringRef getBriefExplanation() const {
75 return StringRef(BriefExplanationStr, BriefExplanationLen);
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +000076 }
Chris Lattner5f9e2722011-07-23 10:55:15 +000077 StringRef getFullExplanation() const {
78 return StringRef(FullExplanationStr, FullExplanationLen);
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +000079 }
Douglas Gregor7d2b8c12011-04-15 22:04:17 +000080
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +000081 bool operator<(const StaticDiagInfoRec &RHS) const {
82 return DiagID < RHS.DiagID;
83 }
84};
85
Douglas Gregor7d2b8c12011-04-15 22:04:17 +000086struct StaticDiagNameIndexRec {
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +000087 const char *NameStr;
Douglas Gregor7d2b8c12011-04-15 22:04:17 +000088 unsigned short DiagID;
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +000089 uint8_t NameLen;
90
Chris Lattner5f9e2722011-07-23 10:55:15 +000091 StringRef getName() const {
92 return StringRef(NameStr, NameLen);
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +000093 }
94
Douglas Gregor7d2b8c12011-04-15 22:04:17 +000095 bool operator<(const StaticDiagNameIndexRec &RHS) const {
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +000096 return getName() < RHS.getName();
Douglas Gregor7d2b8c12011-04-15 22:04:17 +000097 }
98
99 bool operator==(const StaticDiagNameIndexRec &RHS) const {
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000100 return getName() == RHS.getName();
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000101 }
102};
103
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000104template <size_t SizeOfStr, typename FieldType>
105class StringSizerHelper {
106 char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1];
107public:
108 enum { Size = SizeOfStr };
109};
110
111} // namespace anonymous
112
113#define STR_SIZE(str, fieldTy) StringSizerHelper<sizeof(str)-1, fieldTy>::Size
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000114
115static const StaticDiagInfoRec StaticDiagInfo[] = {
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000116#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP, \
117 SFINAE,ACCESS,CATEGORY,BRIEF,FULL) \
118 { diag::ENUM, DEFAULT_MAPPING, CLASS, SFINAE, ACCESS, CATEGORY, \
119 STR_SIZE(#ENUM, uint8_t), STR_SIZE(GROUP, uint8_t), \
120 STR_SIZE(DESC, uint16_t), STR_SIZE(BRIEF, uint16_t), \
121 STR_SIZE(FULL, uint16_t), \
122 #ENUM, GROUP, DESC, BRIEF, FULL },
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000123#include "clang/Basic/DiagnosticCommonKinds.inc"
124#include "clang/Basic/DiagnosticDriverKinds.inc"
125#include "clang/Basic/DiagnosticFrontendKinds.inc"
126#include "clang/Basic/DiagnosticLexKinds.inc"
127#include "clang/Basic/DiagnosticParseKinds.inc"
128#include "clang/Basic/DiagnosticASTKinds.inc"
129#include "clang/Basic/DiagnosticSemaKinds.inc"
130#include "clang/Basic/DiagnosticAnalysisKinds.inc"
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000131#undef DIAG
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000132 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000133};
134
135static const unsigned StaticDiagInfoSize =
136 sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1;
137
138/// To be sorted before first use (since it's splitted among multiple files)
Benjamin Kramer81f9d142011-06-14 13:15:38 +0000139static const StaticDiagNameIndexRec StaticDiagNameIndex[] = {
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000140#define DIAG_NAME_INDEX(ENUM) { #ENUM, diag::ENUM, STR_SIZE(#ENUM, uint8_t) },
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000141#include "clang/Basic/DiagnosticIndexName.inc"
142#undef DIAG_NAME_INDEX
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000143 { 0, 0, 0 }
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000144};
145
146static const unsigned StaticDiagNameIndexSize =
147 sizeof(StaticDiagNameIndex)/sizeof(StaticDiagNameIndex[0])-1;
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000148
149/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
150/// or null if the ID is invalid.
151static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000152 // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
153#ifndef NDEBUG
154 static bool IsFirst = true;
155 if (IsFirst) {
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000156 for (unsigned i = 1; i != StaticDiagInfoSize; ++i) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000157 assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID &&
158 "Diag ID conflict, the enums at the start of clang::diag (in "
Fariborz Jahanianf84109e2011-01-07 18:59:25 +0000159 "DiagnosticIDs.h) probably need to be increased");
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000160
161 assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&
162 "Improperly sorted diag info");
163 }
164 IsFirst = false;
165 }
166#endif
167
168 // Search the diagnostic table with a binary search.
Jeffrey Yasskin7c5109b2011-08-13 05:47:04 +0000169 StaticDiagInfoRec Find = { static_cast<unsigned short>(DiagID),
170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000171
172 const StaticDiagInfoRec *Found =
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000173 std::lower_bound(StaticDiagInfo, StaticDiagInfo + StaticDiagInfoSize, Find);
174 if (Found == StaticDiagInfo + StaticDiagInfoSize ||
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000175 Found->DiagID != DiagID)
176 return 0;
177
178 return Found;
179}
180
181static unsigned GetDefaultDiagMapping(unsigned DiagID) {
182 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
183 return Info->Mapping;
184 return diag::MAP_FATAL;
185}
186
187/// getWarningOptionForDiag - Return the lowest-level warning option that
188/// enables the specified diagnostic. If there is no -Wfoo flag that controls
189/// the diagnostic, this returns null.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000190StringRef DiagnosticIDs::getWarningOptionForDiag(unsigned DiagID) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000191 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000192 return Info->getOptionGroup();
Chris Lattner5f9e2722011-07-23 10:55:15 +0000193 return StringRef();
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000194}
195
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000196/// getCategoryNumberForDiag - Return the category number that a specified
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000197/// DiagID belongs to, or 0 if no category.
198unsigned DiagnosticIDs::getCategoryNumberForDiag(unsigned DiagID) {
199 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
200 return Info->Category;
201 return 0;
202}
203
Benjamin Kramerdbda5132011-06-13 18:38:45 +0000204namespace {
205 // The diagnostic category names.
206 struct StaticDiagCategoryRec {
207 const char *NameStr;
208 uint8_t NameLen;
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000209
Chris Lattner5f9e2722011-07-23 10:55:15 +0000210 StringRef getName() const {
211 return StringRef(NameStr, NameLen);
Benjamin Kramerdbda5132011-06-13 18:38:45 +0000212 }
213 };
214}
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000215
Benjamin Kramerdbda5132011-06-13 18:38:45 +0000216static const StaticDiagCategoryRec CategoryNameTable[] = {
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000217#define GET_CATEGORY_TABLE
John McCall923cd572011-06-15 21:46:43 +0000218#define CATEGORY(X, ENUM) { X, STR_SIZE(X, uint8_t) },
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000219#include "clang/Basic/DiagnosticGroups.inc"
220#undef GET_CATEGORY_TABLE
221 { 0, 0 }
222};
223
224/// getNumberOfCategories - Return the number of categories
225unsigned DiagnosticIDs::getNumberOfCategories() {
226 return sizeof(CategoryNameTable) / sizeof(CategoryNameTable[0])-1;
227}
228
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000229/// getCategoryNameFromID - Given a category ID, return the name of the
230/// category, an empty string if CategoryID is zero, or null if CategoryID is
231/// invalid.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000232StringRef DiagnosticIDs::getCategoryNameFromID(unsigned CategoryID) {
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000233 if (CategoryID >= getNumberOfCategories())
Chris Lattner5f9e2722011-07-23 10:55:15 +0000234 return StringRef();
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000235 return CategoryNameTable[CategoryID].getName();
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000236}
237
238
239
240DiagnosticIDs::SFINAEResponse
241DiagnosticIDs::getDiagnosticSFINAEResponse(unsigned DiagID) {
242 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) {
Douglas Gregor418df342011-01-27 21:06:28 +0000243 if (Info->AccessControl)
244 return SFINAE_AccessControl;
245
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000246 if (!Info->SFINAE)
247 return SFINAE_Report;
248
249 if (Info->Class == CLASS_ERROR)
250 return SFINAE_SubstitutionFailure;
251
252 // Suppress notes, warnings, and extensions;
253 return SFINAE_Suppress;
254 }
255
256 return SFINAE_Report;
257}
258
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000259/// getName - Given a diagnostic ID, return its name
Chris Lattner5f9e2722011-07-23 10:55:15 +0000260StringRef DiagnosticIDs::getName(unsigned DiagID) {
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000261 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000262 return Info->getName();
Chris Lattner5f9e2722011-07-23 10:55:15 +0000263 return StringRef();
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000264}
265
266/// getIdFromName - Given a diagnostic name, return its ID, or 0
Chris Lattner5f9e2722011-07-23 10:55:15 +0000267unsigned DiagnosticIDs::getIdFromName(StringRef Name) {
Benjamin Kramer81f9d142011-06-14 13:15:38 +0000268 const StaticDiagNameIndexRec *StaticDiagNameIndexEnd =
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000269 StaticDiagNameIndex + StaticDiagNameIndexSize;
270
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000271 if (Name.empty()) { return diag::DIAG_UPPER_LIMIT; }
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000272
Jeffrey Yasskin7c5109b2011-08-13 05:47:04 +0000273 assert(Name.size() == static_cast<uint8_t>(Name.size()) &&
274 "Name is too long");
275 StaticDiagNameIndexRec Find = { Name.data(), 0,
276 static_cast<uint8_t>(Name.size()) };
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000277
278 const StaticDiagNameIndexRec *Found =
279 std::lower_bound( StaticDiagNameIndex, StaticDiagNameIndexEnd, Find);
280 if (Found == StaticDiagNameIndexEnd ||
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000281 Found->getName() != Name)
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000282 return diag::DIAG_UPPER_LIMIT;
283
284 return Found->DiagID;
285}
286
287/// getBriefExplanation - Given a diagnostic ID, return a brief explanation
288/// of the issue
Chris Lattner5f9e2722011-07-23 10:55:15 +0000289StringRef DiagnosticIDs::getBriefExplanation(unsigned DiagID) {
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000290 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000291 return Info->getBriefExplanation();
Chris Lattner5f9e2722011-07-23 10:55:15 +0000292 return StringRef();
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000293}
294
295/// getFullExplanation - Given a diagnostic ID, return a full explanation
296/// of the issue
Chris Lattner5f9e2722011-07-23 10:55:15 +0000297StringRef DiagnosticIDs::getFullExplanation(unsigned DiagID) {
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000298 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000299 return Info->getFullExplanation();
Chris Lattner5f9e2722011-07-23 10:55:15 +0000300 return StringRef();
Douglas Gregor7d2b8c12011-04-15 22:04:17 +0000301}
302
303/// getBuiltinDiagClass - Return the class field of the diagnostic.
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000304///
305static unsigned getBuiltinDiagClass(unsigned DiagID) {
306 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
307 return Info->Class;
308 return ~0U;
309}
310
311//===----------------------------------------------------------------------===//
Ted Kremenek6948bc42011-08-09 03:39:14 +0000312// diag_iterator
313//===----------------------------------------------------------------------===//
314
315llvm::StringRef DiagnosticIDs::diag_iterator::getDiagName() const {
316 return static_cast<const StaticDiagNameIndexRec*>(impl)->getName();
317}
318
319unsigned DiagnosticIDs::diag_iterator::getDiagID() const {
320 return static_cast<const StaticDiagNameIndexRec*>(impl)->DiagID;
321}
322
323DiagnosticIDs::diag_iterator &DiagnosticIDs::diag_iterator::operator++() {
324 const StaticDiagNameIndexRec* ptr =
325 static_cast<const StaticDiagNameIndexRec*>(impl);;
326 ++ptr;
327 impl = ptr;
328 return *this;
329}
330
331DiagnosticIDs::diag_iterator DiagnosticIDs::diags_begin() {
332 return DiagnosticIDs::diag_iterator(StaticDiagNameIndex);
333}
334
335DiagnosticIDs::diag_iterator DiagnosticIDs::diags_end() {
336 return DiagnosticIDs::diag_iterator(StaticDiagNameIndex +
337 StaticDiagNameIndexSize);
338}
339
340//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000341// Custom Diagnostic information
342//===----------------------------------------------------------------------===//
343
344namespace clang {
345 namespace diag {
346 class CustomDiagInfo {
347 typedef std::pair<DiagnosticIDs::Level, std::string> DiagDesc;
348 std::vector<DiagDesc> DiagInfo;
349 std::map<DiagDesc, unsigned> DiagIDs;
350 public:
351
352 /// getDescription - Return the description of the specified custom
353 /// diagnostic.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000354 StringRef getDescription(unsigned DiagID) const {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000355 assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
356 "Invalid diagnosic ID");
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000357 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second;
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000358 }
359
360 /// getLevel - Return the level of the specified custom diagnostic.
361 DiagnosticIDs::Level getLevel(unsigned DiagID) const {
362 assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() &&
363 "Invalid diagnosic ID");
364 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first;
365 }
366
Chris Lattner5f9e2722011-07-23 10:55:15 +0000367 unsigned getOrCreateDiagID(DiagnosticIDs::Level L, StringRef Message,
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000368 DiagnosticIDs &Diags) {
369 DiagDesc D(L, Message);
370 // Check to see if it already exists.
371 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D);
372 if (I != DiagIDs.end() && I->first == D)
373 return I->second;
374
375 // If not, assign a new ID.
376 unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT;
377 DiagIDs.insert(std::make_pair(D, ID));
378 DiagInfo.push_back(D);
379 return ID;
380 }
381 };
382
383 } // end diag namespace
384} // end clang namespace
385
386
387//===----------------------------------------------------------------------===//
388// Common Diagnostic implementation
389//===----------------------------------------------------------------------===//
390
391DiagnosticIDs::DiagnosticIDs() {
392 CustomDiagInfo = 0;
393}
394
395DiagnosticIDs::~DiagnosticIDs() {
396 delete CustomDiagInfo;
397}
398
399/// getCustomDiagID - Return an ID for a diagnostic with the specified message
400/// and level. If this is the first request for this diagnosic, it is
401/// registered and created, otherwise the existing ID is returned.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000402unsigned DiagnosticIDs::getCustomDiagID(Level L, StringRef Message) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000403 if (CustomDiagInfo == 0)
404 CustomDiagInfo = new diag::CustomDiagInfo();
405 return CustomDiagInfo->getOrCreateDiagID(L, Message, *this);
406}
407
408
409/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic
410/// level of the specified diagnostic ID is a Warning or Extension.
411/// This only works on builtin diagnostics, not custom ones, and is not legal to
412/// call on NOTEs.
413bool DiagnosticIDs::isBuiltinWarningOrExtension(unsigned DiagID) {
414 return DiagID < diag::DIAG_UPPER_LIMIT &&
415 getBuiltinDiagClass(DiagID) != CLASS_ERROR;
416}
417
418/// \brief Determine whether the given built-in diagnostic ID is a
419/// Note.
420bool DiagnosticIDs::isBuiltinNote(unsigned DiagID) {
421 return DiagID < diag::DIAG_UPPER_LIMIT &&
422 getBuiltinDiagClass(DiagID) == CLASS_NOTE;
423}
424
425/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic
426/// ID is for an extension of some sort. This also returns EnabledByDefault,
427/// which is set to indicate whether the diagnostic is ignored by default (in
428/// which case -pedantic enables it) or treated as a warning/error by default.
429///
430bool DiagnosticIDs::isBuiltinExtensionDiag(unsigned DiagID,
431 bool &EnabledByDefault) {
432 if (DiagID >= diag::DIAG_UPPER_LIMIT ||
433 getBuiltinDiagClass(DiagID) != CLASS_EXTENSION)
434 return false;
435
436 EnabledByDefault = GetDefaultDiagMapping(DiagID) != diag::MAP_IGNORE;
437 return true;
438}
439
440/// getDescription - Given a diagnostic ID, return a description of the
441/// issue.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000442StringRef DiagnosticIDs::getDescription(unsigned DiagID) const {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000443 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID))
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000444 return Info->getDescription();
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000445 return CustomDiagInfo->getDescription(DiagID);
446}
447
448/// getDiagnosticLevel - Based on the way the client configured the Diagnostic
449/// object, classify the specified diagnostic ID into a Level, consumable by
450/// the DiagnosticClient.
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000451DiagnosticIDs::Level
452DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
Ted Kremenek7decebf2011-02-25 01:28:26 +0000453 const Diagnostic &Diag,
454 diag::Mapping *mapping) const {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000455 // Handle custom diagnostics, which cannot be mapped.
456 if (DiagID >= diag::DIAG_UPPER_LIMIT)
457 return CustomDiagInfo->getLevel(DiagID);
458
459 unsigned DiagClass = getBuiltinDiagClass(DiagID);
460 assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!");
Ted Kremenek7decebf2011-02-25 01:28:26 +0000461 return getDiagnosticLevel(DiagID, DiagClass, Loc, Diag, mapping);
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000462}
463
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000464/// \brief Based on the way the client configured the Diagnostic
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000465/// object, classify the specified diagnostic ID into a Level, consumable by
466/// the DiagnosticClient.
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000467///
468/// \param Loc The source location we are interested in finding out the
469/// diagnostic state. Can be null in order to query the latest state.
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000470DiagnosticIDs::Level
471DiagnosticIDs::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass,
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000472 SourceLocation Loc,
Ted Kremenek7decebf2011-02-25 01:28:26 +0000473 const Diagnostic &Diag,
474 diag::Mapping *mapping) const {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000475 // Specific non-error diagnostics may be mapped to various levels from ignored
476 // to error. Errors can only be mapped to fatal.
477 DiagnosticIDs::Level Result = DiagnosticIDs::Fatal;
478
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000479 Diagnostic::DiagStatePointsTy::iterator
480 Pos = Diag.GetDiagStatePointForLoc(Loc);
481 Diagnostic::DiagState *State = Pos->State;
482
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000483 // Get the mapping information, if unset, compute it lazily.
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000484 unsigned MappingInfo = Diag.getDiagnosticMappingInfo((diag::kind)DiagID,
485 State);
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000486 if (MappingInfo == 0) {
487 MappingInfo = GetDefaultDiagMapping(DiagID);
Argyrios Kyrtzidis3efd52c2011-01-14 20:54:07 +0000488 Diag.setDiagnosticMappingInternal(DiagID, MappingInfo, State, false, false);
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000489 }
Ted Kremenek7decebf2011-02-25 01:28:26 +0000490
491 if (mapping)
492 *mapping = (diag::Mapping) (MappingInfo & 7);
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000493
Argyrios Kyrtzidis144bc082011-04-21 23:08:23 +0000494 bool ShouldEmitInSystemHeader = false;
495
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000496 switch (MappingInfo & 7) {
497 default: assert(0 && "Unknown mapping!");
498 case diag::MAP_IGNORE:
Ted Kremenek1e473cc2011-08-18 01:12:56 +0000499 if (Diag.EnableAllWarnings) {
500 // Leave the warning disabled if it was explicitly ignored.
501 if ((MappingInfo & 8) != 0)
502 return DiagnosticIDs::Ignored;
503
504 Result = Diag.WarningsAsErrors ? DiagnosticIDs::Error
505 : DiagnosticIDs::Warning;
506 }
507 // Otherwise, ignore this diagnostic unless this is an extension diagnostic
508 // and we're mapping them onto warnings or errors.
509 else if (!isBuiltinExtensionDiag(DiagID) || // Not an extension
510 Diag.ExtBehavior == Diagnostic::Ext_Ignore || // Ext ignored
511 (MappingInfo & 8) != 0) { // User explicitly mapped it.
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000512 return DiagnosticIDs::Ignored;
Ted Kremenek1e473cc2011-08-18 01:12:56 +0000513 }
514 else {
515 Result = DiagnosticIDs::Warning;
516 }
517
518 if (Diag.ExtBehavior == Diagnostic::Ext_Error)
519 Result = DiagnosticIDs::Error;
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000520 if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
521 Result = DiagnosticIDs::Fatal;
522 break;
523 case diag::MAP_ERROR:
524 Result = DiagnosticIDs::Error;
525 if (Diag.ErrorsAsFatal)
526 Result = DiagnosticIDs::Fatal;
527 break;
528 case diag::MAP_FATAL:
529 Result = DiagnosticIDs::Fatal;
530 break;
Argyrios Kyrtzidis144bc082011-04-21 23:08:23 +0000531 case diag::MAP_WARNING_SHOW_IN_SYSTEM_HEADER:
532 ShouldEmitInSystemHeader = true;
533 // continue as MAP_WARNING.
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000534 case diag::MAP_WARNING:
535 // If warnings are globally mapped to ignore or error, do it.
536 if (Diag.IgnoreAllWarnings)
537 return DiagnosticIDs::Ignored;
538
539 Result = DiagnosticIDs::Warning;
540
541 // If this is an extension diagnostic and we're in -pedantic-error mode, and
542 // if the user didn't explicitly map it, upgrade to an error.
543 if (Diag.ExtBehavior == Diagnostic::Ext_Error &&
544 (MappingInfo & 8) == 0 &&
545 isBuiltinExtensionDiag(DiagID))
546 Result = DiagnosticIDs::Error;
547
548 if (Diag.WarningsAsErrors)
549 Result = DiagnosticIDs::Error;
550 if (Result == DiagnosticIDs::Error && Diag.ErrorsAsFatal)
551 Result = DiagnosticIDs::Fatal;
552 break;
553
554 case diag::MAP_WARNING_NO_WERROR:
555 // Diagnostics specified with -Wno-error=foo should be set to warnings, but
556 // not be adjusted by -Werror or -pedantic-errors.
557 Result = DiagnosticIDs::Warning;
558
559 // If warnings are globally mapped to ignore or error, do it.
560 if (Diag.IgnoreAllWarnings)
561 return DiagnosticIDs::Ignored;
562
563 break;
564
565 case diag::MAP_ERROR_NO_WFATAL:
566 // Diagnostics specified as -Wno-fatal-error=foo should be errors, but
567 // unaffected by -Wfatal-errors.
568 Result = DiagnosticIDs::Error;
569 break;
570 }
571
572 // Okay, we're about to return this as a "diagnostic to emit" one last check:
573 // if this is any sort of extension warning, and if we're in an __extension__
574 // block, silence it.
575 if (Diag.AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID))
576 return DiagnosticIDs::Ignored;
577
Argyrios Kyrtzidiscfdadfe2011-04-21 23:08:18 +0000578 // If we are in a system header, we ignore it.
579 // We also want to ignore extensions and warnings in -Werror and
580 // -pedantic-errors modes, which *map* warnings/extensions to errors.
581 if (Result >= DiagnosticIDs::Warning &&
582 DiagClass != CLASS_ERROR &&
583 // Custom diagnostics always are emitted in system headers.
584 DiagID < diag::DIAG_UPPER_LIMIT &&
Argyrios Kyrtzidis144bc082011-04-21 23:08:23 +0000585 !ShouldEmitInSystemHeader &&
Argyrios Kyrtzidiscfdadfe2011-04-21 23:08:18 +0000586 Diag.SuppressSystemWarnings &&
587 Loc.isValid() &&
588 Diag.getSourceManager().isInSystemHeader(
Chandler Carruth40278532011-07-25 16:49:02 +0000589 Diag.getSourceManager().getExpansionLoc(Loc)))
Argyrios Kyrtzidiscfdadfe2011-04-21 23:08:18 +0000590 return DiagnosticIDs::Ignored;
591
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000592 return Result;
593}
594
Benjamin Kramerdbda5132011-06-13 18:38:45 +0000595namespace {
596 struct WarningOption {
597 // Be safe with the size of 'NameLen' because we don't statically check if
598 // the size will fit in the field; the struct size won't decrease with a
599 // shorter type anyway.
600 size_t NameLen;
601 const char *NameStr;
602 const short *Members;
603 const short *SubGroups;
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000604
Chris Lattner5f9e2722011-07-23 10:55:15 +0000605 StringRef getName() const {
606 return StringRef(NameStr, NameLen);
Benjamin Kramerdbda5132011-06-13 18:38:45 +0000607 }
608 };
609}
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000610
611#define GET_DIAG_ARRAYS
612#include "clang/Basic/DiagnosticGroups.inc"
613#undef GET_DIAG_ARRAYS
614
615// Second the table of options, sorted by name for fast binary lookup.
616static const WarningOption OptionTable[] = {
617#define GET_DIAG_TABLE
618#include "clang/Basic/DiagnosticGroups.inc"
619#undef GET_DIAG_TABLE
620};
621static const size_t OptionTableSize =
622sizeof(OptionTable) / sizeof(OptionTable[0]);
623
624static bool WarningOptionCompare(const WarningOption &LHS,
625 const WarningOption &RHS) {
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000626 return LHS.getName() < RHS.getName();
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000627}
628
629static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping,
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000630 SourceLocation Loc, Diagnostic &Diag) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000631 // Option exists, poke all the members of its diagnostic set.
632 if (const short *Member = Group->Members) {
633 for (; *Member != -1; ++Member)
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000634 Diag.setDiagnosticMapping(*Member, Mapping, Loc);
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000635 }
636
637 // Enable/disable all subgroups along with this one.
638 if (const short *SubGroups = Group->SubGroups) {
639 for (; *SubGroups != (short)-1; ++SubGroups)
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000640 MapGroupMembers(&OptionTable[(short)*SubGroups], Mapping, Loc, Diag);
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000641 }
642}
643
644/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
645/// "unknown-pragmas" to have the specified mapping. This returns true and
646/// ignores the request if "Group" was unknown, false otherwise.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000647bool DiagnosticIDs::setDiagnosticGroupMapping(StringRef Group,
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000648 diag::Mapping Map,
649 SourceLocation Loc,
650 Diagnostic &Diag) const {
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000651 assert((Loc.isValid() ||
652 Diag.DiagStatePoints.empty() ||
653 Diag.DiagStatePoints.back().Loc.isInvalid()) &&
654 "Loc should be invalid only when the mapping comes from command-line");
655 assert((Loc.isInvalid() || Diag.DiagStatePoints.empty() ||
656 Diag.DiagStatePoints.back().Loc.isInvalid() ||
657 !Diag.SourceMgr->isBeforeInTranslationUnit(Loc,
658 Diag.DiagStatePoints.back().Loc)) &&
659 "Source location of new mapping is before the previous one!");
660
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000661 WarningOption Key = { Group.size(), Group.data(), 0, 0 };
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000662 const WarningOption *Found =
663 std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key,
664 WarningOptionCompare);
665 if (Found == OptionTable + OptionTableSize ||
Argyrios Kyrtzidis477aab62011-05-25 05:05:01 +0000666 Found->getName() != Group)
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000667 return true; // Option not found.
668
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000669 MapGroupMembers(Found, Map, Loc, Diag);
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000670 return false;
671}
672
673/// ProcessDiag - This is the method used to report a diagnostic that is
674/// finally fully formed.
675bool DiagnosticIDs::ProcessDiag(Diagnostic &Diag) const {
676 DiagnosticInfo Info(&Diag);
677
678 if (Diag.SuppressAllDiagnostics)
679 return false;
680
681 assert(Diag.getClient() && "DiagnosticClient not set!");
682
683 // Figure out the diagnostic level of this message.
684 DiagnosticIDs::Level DiagLevel;
685 unsigned DiagID = Info.getID();
686
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000687 if (DiagID >= diag::DIAG_UPPER_LIMIT) {
688 // Handle custom diagnostics, which cannot be mapped.
689 DiagLevel = CustomDiagInfo->getLevel(DiagID);
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000690 } else {
691 // Get the class of the diagnostic. If this is a NOTE, map it onto whatever
692 // the diagnostic level was for the previous diagnostic so that it is
693 // filtered the same as the previous diagnostic.
694 unsigned DiagClass = getBuiltinDiagClass(DiagID);
695 if (DiagClass == CLASS_NOTE) {
696 DiagLevel = DiagnosticIDs::Note;
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000697 } else {
Argyrios Kyrtzidis08274082010-12-15 18:44:22 +0000698 DiagLevel = getDiagnosticLevel(DiagID, DiagClass, Info.getLocation(),
699 Diag);
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000700 }
701 }
702
703 if (DiagLevel != DiagnosticIDs::Note) {
704 // Record that a fatal error occurred only when we see a second
705 // non-note diagnostic. This allows notes to be attached to the
706 // fatal error, but suppresses any diagnostics that follow those
707 // notes.
708 if (Diag.LastDiagLevel == DiagnosticIDs::Fatal)
709 Diag.FatalErrorOccurred = true;
710
711 Diag.LastDiagLevel = DiagLevel;
712 }
713
Argyrios Kyrtzidisc0a575f2011-07-29 01:25:44 +0000714 // Update counts for DiagnosticErrorTrap even if a fatal error occurred.
715 if (DiagLevel >= DiagnosticIDs::Error) {
716 ++Diag.TrapNumErrorsOccurred;
717 if (isUnrecoverable(DiagID))
718 ++Diag.TrapNumUnrecoverableErrorsOccurred;
719 }
720
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000721 // If a fatal error has already been emitted, silence all subsequent
722 // diagnostics.
723 if (Diag.FatalErrorOccurred) {
724 if (DiagLevel >= DiagnosticIDs::Error &&
725 Diag.Client->IncludeInDiagnosticCounts()) {
726 ++Diag.NumErrors;
727 ++Diag.NumErrorsSuppressed;
728 }
729
730 return false;
731 }
732
733 // If the client doesn't care about this message, don't issue it. If this is
734 // a note and the last real diagnostic was ignored, ignore it too.
735 if (DiagLevel == DiagnosticIDs::Ignored ||
736 (DiagLevel == DiagnosticIDs::Note &&
737 Diag.LastDiagLevel == DiagnosticIDs::Ignored))
738 return false;
739
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000740 if (DiagLevel >= DiagnosticIDs::Error) {
Argyrios Kyrtzidisc0a575f2011-07-29 01:25:44 +0000741 if (isUnrecoverable(DiagID))
Douglas Gregor85bea972011-07-06 17:40:26 +0000742 Diag.UnrecoverableErrorOccurred = true;
Douglas Gregor85bea972011-07-06 17:40:26 +0000743
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000744 if (Diag.Client->IncludeInDiagnosticCounts()) {
745 Diag.ErrorOccurred = true;
746 ++Diag.NumErrors;
747 }
748
Douglas Gregorf1d59482011-08-17 19:13:00 +0000749 // If we've emitted a lot of errors, emit a fatal error instead of it to
750 // stop a flood of bogus errors.
751 if (Diag.ErrorLimit && Diag.NumErrors > Diag.ErrorLimit &&
752 DiagLevel == DiagnosticIDs::Error) {
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000753 Diag.SetDelayedDiagnostic(diag::fatal_too_many_errors);
Douglas Gregorf1d59482011-08-17 19:13:00 +0000754 return false;
755 }
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000756 }
757
Douglas Gregor4814fb52011-02-03 23:41:12 +0000758 // If we have any Fix-Its, make sure that all of the Fix-Its point into
Chandler Carruth3201f382011-07-26 05:17:23 +0000759 // source locations that aren't macro expansions. If any point into macro
760 // expansions, remove all of the Fix-Its.
Douglas Gregor4814fb52011-02-03 23:41:12 +0000761 for (unsigned I = 0, N = Diag.NumFixItHints; I != N; ++I) {
762 const FixItHint &FixIt = Diag.FixItHints[I];
763 if (FixIt.RemoveRange.isInvalid() ||
764 FixIt.RemoveRange.getBegin().isMacroID() ||
765 FixIt.RemoveRange.getEnd().isMacroID()) {
766 Diag.NumFixItHints = 0;
767 break;
768 }
769 }
770
Argyrios Kyrtzidis33e4e702010-11-18 20:06:41 +0000771 // Finally, report it.
772 Diag.Client->HandleDiagnostic((Diagnostic::Level)DiagLevel, Info);
773 if (Diag.Client->IncludeInDiagnosticCounts()) {
774 if (DiagLevel == DiagnosticIDs::Warning)
775 ++Diag.NumWarnings;
776 }
777
778 Diag.CurDiagID = ~0U;
779
780 return true;
781}
John McCall923cd572011-06-15 21:46:43 +0000782
783bool DiagnosticIDs::isUnrecoverable(unsigned DiagID) const {
784 if (DiagID >= diag::DIAG_UPPER_LIMIT) {
785 // Custom diagnostics.
786 return CustomDiagInfo->getLevel(DiagID) >= DiagnosticIDs::Error;
787 }
788
789 // Only errors may be unrecoverable.
Douglas Gregor85bea972011-07-06 17:40:26 +0000790 if (getBuiltinDiagClass(DiagID) < CLASS_ERROR)
John McCall923cd572011-06-15 21:46:43 +0000791 return false;
792
793 if (DiagID == diag::err_unavailable ||
794 DiagID == diag::err_unavailable_message)
795 return false;
796
John McCallf85e1932011-06-15 23:02:42 +0000797 // Currently we consider all ARC errors as recoverable.
798 if (getCategoryNumberForDiag(DiagID) ==
799 diag::DiagCat_Automatic_Reference_Counting_Issue)
800 return false;
801
John McCall923cd572011-06-15 21:46:43 +0000802 return true;
803}