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