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