/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/include/clang/Basic/DiagnosticIDs.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- DiagnosticIDs.h - Diagnostic IDs Handling --------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | /// |
9 | | /// \file |
10 | | /// Defines the Diagnostic IDs-related interfaces. |
11 | | /// |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #ifndef LLVM_CLANG_BASIC_DIAGNOSTICIDS_H |
15 | | #define LLVM_CLANG_BASIC_DIAGNOSTICIDS_H |
16 | | |
17 | | #include "clang/Basic/LLVM.h" |
18 | | #include "llvm/ADT/IntrusiveRefCntPtr.h" |
19 | | #include "llvm/ADT/StringRef.h" |
20 | | #include <vector> |
21 | | |
22 | | namespace clang { |
23 | | class DiagnosticsEngine; |
24 | | class SourceLocation; |
25 | | |
26 | | // Import the diagnostic enums themselves. |
27 | | namespace diag { |
28 | | // Size of each of the diagnostic categories. |
29 | | enum { |
30 | | DIAG_SIZE_COMMON = 300, |
31 | | DIAG_SIZE_DRIVER = 200, |
32 | | DIAG_SIZE_FRONTEND = 150, |
33 | | DIAG_SIZE_SERIALIZATION = 120, |
34 | | DIAG_SIZE_LEX = 400, |
35 | | DIAG_SIZE_PARSE = 600, |
36 | | DIAG_SIZE_AST = 200, |
37 | | DIAG_SIZE_COMMENT = 100, |
38 | | DIAG_SIZE_CROSSTU = 100, |
39 | | DIAG_SIZE_SEMA = 4000, |
40 | | DIAG_SIZE_ANALYSIS = 100, |
41 | | DIAG_SIZE_REFACTORING = 1000, |
42 | | }; |
43 | | // Start position for diagnostics. |
44 | | enum { |
45 | | DIAG_START_COMMON = 0, |
46 | | DIAG_START_DRIVER = DIAG_START_COMMON + DIAG_SIZE_COMMON, |
47 | | DIAG_START_FRONTEND = DIAG_START_DRIVER + DIAG_SIZE_DRIVER, |
48 | | DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + DIAG_SIZE_FRONTEND, |
49 | | DIAG_START_LEX = DIAG_START_SERIALIZATION + DIAG_SIZE_SERIALIZATION, |
50 | | DIAG_START_PARSE = DIAG_START_LEX + DIAG_SIZE_LEX, |
51 | | DIAG_START_AST = DIAG_START_PARSE + DIAG_SIZE_PARSE, |
52 | | DIAG_START_COMMENT = DIAG_START_AST + DIAG_SIZE_AST, |
53 | | DIAG_START_CROSSTU = DIAG_START_COMMENT + DIAG_SIZE_COMMENT, |
54 | | DIAG_START_SEMA = DIAG_START_CROSSTU + DIAG_SIZE_CROSSTU, |
55 | | DIAG_START_ANALYSIS = DIAG_START_SEMA + DIAG_SIZE_SEMA, |
56 | | DIAG_START_REFACTORING = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS, |
57 | | DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + DIAG_SIZE_REFACTORING |
58 | | }; |
59 | | |
60 | | class CustomDiagInfo; |
61 | | |
62 | | /// All of the diagnostics that can be emitted by the frontend. |
63 | | typedef unsigned kind; |
64 | | |
65 | | // Get typedefs for common diagnostics. |
66 | | enum { |
67 | | #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ |
68 | | SFINAE,CATEGORY,NOWERROR,SHOWINSYSHEADER) ENUM, |
69 | | #define COMMONSTART |
70 | | #include "clang/Basic/DiagnosticCommonKinds.inc" |
71 | | NUM_BUILTIN_COMMON_DIAGNOSTICS |
72 | | #undef DIAG |
73 | | }; |
74 | | |
75 | | /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs |
76 | | /// to either Ignore (nothing), Remark (emit a remark), Warning |
77 | | /// (emit a warning) or Error (emit as an error). It allows clients to |
78 | | /// map ERRORs to Error or Fatal (stop emitting diagnostics after this one). |
79 | | enum class Severity { |
80 | | // NOTE: 0 means "uncomputed". |
81 | | Ignored = 1, ///< Do not present this diagnostic, ignore it. |
82 | | Remark = 2, ///< Present this diagnostic as a remark. |
83 | | Warning = 3, ///< Present this diagnostic as a warning. |
84 | | Error = 4, ///< Present this diagnostic as an error. |
85 | | Fatal = 5 ///< Present this diagnostic as a fatal error. |
86 | | }; |
87 | | |
88 | | /// Flavors of diagnostics we can emit. Used to filter for a particular |
89 | | /// kind of diagnostic (for instance, for -W/-R flags). |
90 | | enum class Flavor { |
91 | | WarningOrError, ///< A diagnostic that indicates a problem or potential |
92 | | ///< problem. Can be made fatal by -Werror. |
93 | | Remark ///< A diagnostic that indicates normal progress through |
94 | | ///< compilation. |
95 | | }; |
96 | | } |
97 | | |
98 | | class DiagnosticMapping { |
99 | | unsigned Severity : 3; |
100 | | unsigned IsUser : 1; |
101 | | unsigned IsPragma : 1; |
102 | | unsigned HasNoWarningAsError : 1; |
103 | | unsigned HasNoErrorAsFatal : 1; |
104 | | unsigned WasUpgradedFromWarning : 1; |
105 | | |
106 | | public: |
107 | | static DiagnosticMapping Make(diag::Severity Severity, bool IsUser, |
108 | 5.46M | bool IsPragma) { |
109 | 5.46M | DiagnosticMapping Result; |
110 | 5.46M | Result.Severity = (unsigned)Severity; |
111 | 5.46M | Result.IsUser = IsUser; |
112 | 5.46M | Result.IsPragma = IsPragma; |
113 | 5.46M | Result.HasNoWarningAsError = 0; |
114 | 5.46M | Result.HasNoErrorAsFatal = 0; |
115 | 5.46M | Result.WasUpgradedFromWarning = 0; |
116 | 5.46M | return Result; |
117 | 5.46M | } |
118 | | |
119 | 203M | diag::Severity getSeverity() const { return (diag::Severity)Severity; } |
120 | 3.30M | void setSeverity(diag::Severity Value) { Severity = (unsigned)Value; } |
121 | | |
122 | 205k | bool isUser() const { return IsUser; } |
123 | 144k | bool isPragma() const { return IsPragma; } |
124 | | |
125 | 2 | bool isErrorOrFatal() const { |
126 | 2 | return getSeverity() == diag::Severity::Error || |
127 | 2 | getSeverity() == diag::Severity::Fatal1 ; |
128 | 2 | } |
129 | | |
130 | 1.35M | bool hasNoWarningAsError() const { return HasNoWarningAsError; } |
131 | 48.5k | void setNoWarningAsError(bool Value) { HasNoWarningAsError = Value; } |
132 | | |
133 | 6 | bool hasNoErrorAsFatal() const { return HasNoErrorAsFatal; } |
134 | 45.2k | void setNoErrorAsFatal(bool Value) { HasNoErrorAsFatal = Value; } |
135 | | |
136 | | /// Whether this mapping attempted to map the diagnostic to a warning, but |
137 | | /// was overruled because the diagnostic was already mapped to an error or |
138 | | /// fatal error. |
139 | 52.9k | bool wasUpgradedFromWarning() const { return WasUpgradedFromWarning; } |
140 | 2.16M | void setUpgradedFromWarning(bool Value) { WasUpgradedFromWarning = Value; } |
141 | | |
142 | | /// Serialize this mapping as a raw integer. |
143 | 32.3k | unsigned serialize() const { |
144 | 32.3k | return (IsUser << 7) | (IsPragma << 6) | (HasNoWarningAsError << 5) | |
145 | 32.3k | (HasNoErrorAsFatal << 4) | (WasUpgradedFromWarning << 3) | Severity; |
146 | 32.3k | } |
147 | | /// Deserialize a mapping. |
148 | 53.5k | static DiagnosticMapping deserialize(unsigned Bits) { |
149 | 53.5k | DiagnosticMapping Result; |
150 | 53.5k | Result.IsUser = (Bits >> 7) & 1; |
151 | 53.5k | Result.IsPragma = (Bits >> 6) & 1; |
152 | 53.5k | Result.HasNoWarningAsError = (Bits >> 5) & 1; |
153 | 53.5k | Result.HasNoErrorAsFatal = (Bits >> 4) & 1; |
154 | 53.5k | Result.WasUpgradedFromWarning = (Bits >> 3) & 1; |
155 | 53.5k | Result.Severity = Bits & 0x7; |
156 | 53.5k | return Result; |
157 | 53.5k | } |
158 | | }; |
159 | | |
160 | | /// Used for handling and querying diagnostic IDs. |
161 | | /// |
162 | | /// Can be used and shared by multiple Diagnostics for multiple translation units. |
163 | | class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> { |
164 | | public: |
165 | | /// The level of the diagnostic, after it has been through mapping. |
166 | | enum Level { |
167 | | Ignored, Note, Remark, Warning, Error, Fatal |
168 | | }; |
169 | | |
170 | | private: |
171 | | /// Information for uniquing and looking up custom diags. |
172 | | std::unique_ptr<diag::CustomDiagInfo> CustomDiagInfo; |
173 | | |
174 | | public: |
175 | | DiagnosticIDs(); |
176 | | ~DiagnosticIDs(); |
177 | | |
178 | | /// Return an ID for a diagnostic with the specified format string and |
179 | | /// level. |
180 | | /// |
181 | | /// If this is the first request for this diagnostic, it is registered and |
182 | | /// created, otherwise the existing ID is returned. |
183 | | |
184 | | // FIXME: Replace this function with a create-only facilty like |
185 | | // createCustomDiagIDFromFormatString() to enforce safe usage. At the time of |
186 | | // writing, nearly all callers of this function were invalid. |
187 | | unsigned getCustomDiagID(Level L, StringRef FormatString); |
188 | | |
189 | | //===--------------------------------------------------------------------===// |
190 | | // Diagnostic classification and reporting interfaces. |
191 | | // |
192 | | |
193 | | /// Given a diagnostic ID, return a description of the issue. |
194 | | StringRef getDescription(unsigned DiagID) const; |
195 | | |
196 | | /// Return true if the unmapped diagnostic levelof the specified |
197 | | /// diagnostic ID is a Warning or Extension. |
198 | | /// |
199 | | /// This only works on builtin diagnostics, not custom ones, and is not |
200 | | /// legal to call on NOTEs. |
201 | | static bool isBuiltinWarningOrExtension(unsigned DiagID); |
202 | | |
203 | | /// Return true if the specified diagnostic is mapped to errors by |
204 | | /// default. |
205 | | static bool isDefaultMappingAsError(unsigned DiagID); |
206 | | |
207 | | /// Determine whether the given built-in diagnostic ID is a Note. |
208 | | static bool isBuiltinNote(unsigned DiagID); |
209 | | |
210 | | /// Determine whether the given built-in diagnostic ID is for an |
211 | | /// extension of some sort. |
212 | 0 | static bool isBuiltinExtensionDiag(unsigned DiagID) { |
213 | 0 | bool ignored; |
214 | 0 | return isBuiltinExtensionDiag(DiagID, ignored); |
215 | 0 | } |
216 | | |
217 | | /// Determine whether the given built-in diagnostic ID is for an |
218 | | /// extension of some sort, and whether it is enabled by default. |
219 | | /// |
220 | | /// This also returns EnabledByDefault, which is set to indicate whether the |
221 | | /// diagnostic is ignored by default (in which case -pedantic enables it) or |
222 | | /// treated as a warning/error by default. |
223 | | /// |
224 | | static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault); |
225 | | |
226 | | |
227 | | /// Return the lowest-level warning option that enables the specified |
228 | | /// diagnostic. |
229 | | /// |
230 | | /// If there is no -Wfoo flag that controls the diagnostic, this returns null. |
231 | | static StringRef getWarningOptionForDiag(unsigned DiagID); |
232 | | |
233 | | /// Return the category number that a specified \p DiagID belongs to, |
234 | | /// or 0 if no category. |
235 | | static unsigned getCategoryNumberForDiag(unsigned DiagID); |
236 | | |
237 | | /// Return the number of diagnostic categories. |
238 | | static unsigned getNumberOfCategories(); |
239 | | |
240 | | /// Given a category ID, return the name of the category. |
241 | | static StringRef getCategoryNameFromID(unsigned CategoryID); |
242 | | |
243 | | /// Return true if a given diagnostic falls into an ARC diagnostic |
244 | | /// category. |
245 | | static bool isARCDiagnostic(unsigned DiagID); |
246 | | |
247 | | /// Enumeration describing how the emission of a diagnostic should |
248 | | /// be treated when it occurs during C++ template argument deduction. |
249 | | enum SFINAEResponse { |
250 | | /// The diagnostic should not be reported, but it should cause |
251 | | /// template argument deduction to fail. |
252 | | /// |
253 | | /// The vast majority of errors that occur during template argument |
254 | | /// deduction fall into this category. |
255 | | SFINAE_SubstitutionFailure, |
256 | | |
257 | | /// The diagnostic should be suppressed entirely. |
258 | | /// |
259 | | /// Warnings generally fall into this category. |
260 | | SFINAE_Suppress, |
261 | | |
262 | | /// The diagnostic should be reported. |
263 | | /// |
264 | | /// The diagnostic should be reported. Various fatal errors (e.g., |
265 | | /// template instantiation depth exceeded) fall into this category. |
266 | | SFINAE_Report, |
267 | | |
268 | | /// The diagnostic is an access-control diagnostic, which will be |
269 | | /// substitution failures in some contexts and reported in others. |
270 | | SFINAE_AccessControl |
271 | | }; |
272 | | |
273 | | /// Determines whether the given built-in diagnostic ID is |
274 | | /// for an error that is suppressed if it occurs during C++ template |
275 | | /// argument deduction. |
276 | | /// |
277 | | /// When an error is suppressed due to SFINAE, the template argument |
278 | | /// deduction fails but no diagnostic is emitted. Certain classes of |
279 | | /// errors, such as those errors that involve C++ access control, |
280 | | /// are not SFINAE errors. |
281 | | static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID); |
282 | | |
283 | | /// Get the string of all diagnostic flags. |
284 | | /// |
285 | | /// \returns A list of all diagnostics flags as they would be written in a |
286 | | /// command line invocation including their `no-` variants. For example: |
287 | | /// `{"-Wempty-body", "-Wno-empty-body", ...}` |
288 | | static std::vector<std::string> getDiagnosticFlags(); |
289 | | |
290 | | /// Get the set of all diagnostic IDs in the group with the given name. |
291 | | /// |
292 | | /// \param[out] Diags - On return, the diagnostics in the group. |
293 | | /// \returns \c true if the given group is unknown, \c false otherwise. |
294 | | bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, |
295 | | SmallVectorImpl<diag::kind> &Diags) const; |
296 | | |
297 | | /// Get the set of all diagnostic IDs. |
298 | | static void getAllDiagnostics(diag::Flavor Flavor, |
299 | | std::vector<diag::kind> &Diags); |
300 | | |
301 | | /// Get the diagnostic option with the closest edit distance to the |
302 | | /// given group name. |
303 | | static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group); |
304 | | |
305 | | private: |
306 | | /// Classify the specified diagnostic ID into a Level, consumable by |
307 | | /// the DiagnosticClient. |
308 | | /// |
309 | | /// The classification is based on the way the client configured the |
310 | | /// DiagnosticsEngine object. |
311 | | /// |
312 | | /// \param Loc The source location for which we are interested in finding out |
313 | | /// the diagnostic state. Can be null in order to query the latest state. |
314 | | DiagnosticIDs::Level |
315 | | getDiagnosticLevel(unsigned DiagID, SourceLocation Loc, |
316 | | const DiagnosticsEngine &Diag) const LLVM_READONLY; |
317 | | |
318 | | diag::Severity |
319 | | getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, |
320 | | const DiagnosticsEngine &Diag) const LLVM_READONLY; |
321 | | |
322 | | /// Used to report a diagnostic that is finally fully formed. |
323 | | /// |
324 | | /// \returns \c true if the diagnostic was emitted, \c false if it was |
325 | | /// suppressed. |
326 | | bool ProcessDiag(DiagnosticsEngine &Diag) const; |
327 | | |
328 | | /// Used to emit a diagnostic that is finally fully formed, |
329 | | /// ignoring suppression. |
330 | | void EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const; |
331 | | |
332 | | /// Whether the diagnostic may leave the AST in a state where some |
333 | | /// invariants can break. |
334 | | bool isUnrecoverable(unsigned DiagID) const; |
335 | | |
336 | | friend class DiagnosticsEngine; |
337 | | }; |
338 | | |
339 | | } // end namespace clang |
340 | | |
341 | | #endif |