1 | //===- Diagnostic.h - C Language Family Diagnostic 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-related interfaces. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_H |
15 | #define LLVM_CLANG_BASIC_DIAGNOSTIC_H |
16 | |
17 | #include "clang/Basic/DiagnosticIDs.h" |
18 | #include "clang/Basic/DiagnosticOptions.h" |
19 | #include "clang/Basic/SourceLocation.h" |
20 | #include "clang/Basic/Specifiers.h" |
21 | #include "llvm/ADT/ArrayRef.h" |
22 | #include "llvm/ADT/DenseMap.h" |
23 | #include "llvm/ADT/IntrusiveRefCntPtr.h" |
24 | #include "llvm/ADT/Optional.h" |
25 | #include "llvm/ADT/SmallVector.h" |
26 | #include "llvm/ADT/StringRef.h" |
27 | #include "llvm/ADT/iterator_range.h" |
28 | #include "llvm/Support/Compiler.h" |
29 | #include <cassert> |
30 | #include <cstdint> |
31 | #include <limits> |
32 | #include <list> |
33 | #include <map> |
34 | #include <memory> |
35 | #include <string> |
36 | #include <type_traits> |
37 | #include <utility> |
38 | #include <vector> |
39 | |
40 | namespace llvm { |
41 | class Error; |
42 | } |
43 | |
44 | namespace clang { |
45 | |
46 | class DeclContext; |
47 | class DiagnosticBuilder; |
48 | class DiagnosticConsumer; |
49 | class IdentifierInfo; |
50 | class LangOptions; |
51 | class Preprocessor; |
52 | class SourceManager; |
53 | class StoredDiagnostic; |
54 | |
55 | namespace tok { |
56 | |
57 | enum TokenKind : unsigned short; |
58 | |
59 | } // namespace tok |
60 | |
61 | /// Annotates a diagnostic with some code that should be |
62 | /// inserted, removed, or replaced to fix the problem. |
63 | /// |
64 | /// This kind of hint should be used when we are certain that the |
65 | /// introduction, removal, or modification of a particular (small!) |
66 | /// amount of code will correct a compilation error. The compiler |
67 | /// should also provide full recovery from such errors, such that |
68 | /// suppressing the diagnostic output can still result in successful |
69 | /// compilation. |
70 | class FixItHint { |
71 | public: |
72 | /// Code that should be replaced to correct the error. Empty for an |
73 | /// insertion hint. |
74 | CharSourceRange RemoveRange; |
75 | |
76 | /// Code in the specific range that should be inserted in the insertion |
77 | /// location. |
78 | CharSourceRange InsertFromRange; |
79 | |
80 | /// The actual code to insert at the insertion location, as a |
81 | /// string. |
82 | std::string CodeToInsert; |
83 | |
84 | bool BeforePreviousInsertions = false; |
85 | |
86 | /// Empty code modification hint, indicating that no code |
87 | /// modification is known. |
88 | FixItHint() = default; |
89 | |
90 | bool isNull() const { |
91 | return !RemoveRange.isValid(); |
92 | } |
93 | |
94 | /// Create a code modification hint that inserts the given |
95 | /// code string at a specific location. |
96 | static FixItHint CreateInsertion(SourceLocation InsertionLoc, |
97 | StringRef Code, |
98 | bool BeforePreviousInsertions = false) { |
99 | FixItHint Hint; |
100 | Hint.RemoveRange = |
101 | CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); |
102 | Hint.CodeToInsert = std::string(Code); |
103 | Hint.BeforePreviousInsertions = BeforePreviousInsertions; |
104 | return Hint; |
105 | } |
106 | |
107 | /// Create a code modification hint that inserts the given |
108 | /// code from \p FromRange at a specific location. |
109 | static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc, |
110 | CharSourceRange FromRange, |
111 | bool BeforePreviousInsertions = false) { |
112 | FixItHint Hint; |
113 | Hint.RemoveRange = |
114 | CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); |
115 | Hint.InsertFromRange = FromRange; |
116 | Hint.BeforePreviousInsertions = BeforePreviousInsertions; |
117 | return Hint; |
118 | } |
119 | |
120 | /// Create a code modification hint that removes the given |
121 | /// source range. |
122 | static FixItHint CreateRemoval(CharSourceRange RemoveRange) { |
123 | FixItHint Hint; |
124 | Hint.RemoveRange = RemoveRange; |
125 | return Hint; |
126 | } |
127 | static FixItHint CreateRemoval(SourceRange RemoveRange) { |
128 | return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange)); |
129 | } |
130 | |
131 | /// Create a code modification hint that replaces the given |
132 | /// source range with the given code string. |
133 | static FixItHint CreateReplacement(CharSourceRange RemoveRange, |
134 | StringRef Code) { |
135 | FixItHint Hint; |
136 | Hint.RemoveRange = RemoveRange; |
137 | Hint.CodeToInsert = std::string(Code); |
138 | return Hint; |
139 | } |
140 | |
141 | static FixItHint CreateReplacement(SourceRange RemoveRange, |
142 | StringRef Code) { |
143 | return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code); |
144 | } |
145 | }; |
146 | |
147 | /// Concrete class used by the front-end to report problems and issues. |
148 | /// |
149 | /// This massages the diagnostics (e.g. handling things like "report warnings |
150 | /// as errors" and passes them off to the DiagnosticConsumer for reporting to |
151 | /// the user. DiagnosticsEngine is tied to one translation unit and one |
152 | /// SourceManager. |
153 | class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { |
154 | public: |
155 | /// The level of the diagnostic, after it has been through mapping. |
156 | enum Level { |
157 | Ignored = DiagnosticIDs::Ignored, |
158 | Note = DiagnosticIDs::Note, |
159 | = DiagnosticIDs::Remark, |
160 | Warning = DiagnosticIDs::Warning, |
161 | Error = DiagnosticIDs::Error, |
162 | Fatal = DiagnosticIDs::Fatal |
163 | }; |
164 | |
165 | enum ArgumentKind { |
166 | /// std::string |
167 | ak_std_string, |
168 | |
169 | /// const char * |
170 | ak_c_string, |
171 | |
172 | /// int |
173 | ak_sint, |
174 | |
175 | /// unsigned |
176 | ak_uint, |
177 | |
178 | /// enum TokenKind : unsigned |
179 | ak_tokenkind, |
180 | |
181 | /// IdentifierInfo |
182 | ak_identifierinfo, |
183 | |
184 | /// address space |
185 | ak_addrspace, |
186 | |
187 | /// Qualifiers |
188 | ak_qual, |
189 | |
190 | /// QualType |
191 | ak_qualtype, |
192 | |
193 | /// DeclarationName |
194 | ak_declarationname, |
195 | |
196 | /// NamedDecl * |
197 | ak_nameddecl, |
198 | |
199 | /// NestedNameSpecifier * |
200 | ak_nestednamespec, |
201 | |
202 | /// DeclContext * |
203 | ak_declcontext, |
204 | |
205 | /// pair<QualType, QualType> |
206 | ak_qualtype_pair, |
207 | |
208 | /// Attr * |
209 | ak_attr |
210 | }; |
211 | |
212 | /// Represents on argument value, which is a union discriminated |
213 | /// by ArgumentKind, with a value. |
214 | using ArgumentValue = std::pair<ArgumentKind, intptr_t>; |
215 | |
216 | private: |
217 | // Used by __extension__ |
218 | unsigned char AllExtensionsSilenced = 0; |
219 | |
220 | // Treat fatal errors like errors. |
221 | bool FatalsAsError = false; |
222 | |
223 | // Suppress all diagnostics. |
224 | bool SuppressAllDiagnostics = false; |
225 | |
226 | // Elide common types of templates. |
227 | bool ElideType = true; |
228 | |
229 | // Print a tree when comparing templates. |
230 | bool PrintTemplateTree = false; |
231 | |
232 | // Color printing is enabled. |
233 | bool ShowColors = false; |
234 | |
235 | // Which overload candidates to show. |
236 | OverloadsShown ShowOverloads = Ovl_All; |
237 | |
238 | // Cap of # errors emitted, 0 -> no limit. |
239 | unsigned ErrorLimit = 0; |
240 | |
241 | // Cap on depth of template backtrace stack, 0 -> no limit. |
242 | unsigned TemplateBacktraceLimit = 0; |
243 | |
244 | // Cap on depth of constexpr evaluation backtrace stack, 0 -> no limit. |
245 | unsigned ConstexprBacktraceLimit = 0; |
246 | |
247 | IntrusiveRefCntPtr<DiagnosticIDs> Diags; |
248 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; |
249 | DiagnosticConsumer *Client = nullptr; |
250 | std::unique_ptr<DiagnosticConsumer> Owner; |
251 | SourceManager *SourceMgr = nullptr; |
252 | |
253 | /// Mapping information for diagnostics. |
254 | /// |
255 | /// Mapping info is packed into four bits per diagnostic. The low three |
256 | /// bits are the mapping (an instance of diag::Severity), or zero if unset. |
257 | /// The high bit is set when the mapping was established as a user mapping. |
258 | /// If the high bit is clear, then the low bits are set to the default |
259 | /// value, and should be mapped with -pedantic, -Werror, etc. |
260 | /// |
261 | /// A new DiagState is created and kept around when diagnostic pragmas modify |
262 | /// the state so that we know what is the diagnostic state at any given |
263 | /// source location. |
264 | class DiagState { |
265 | llvm::DenseMap<unsigned, DiagnosticMapping> DiagMap; |
266 | |
267 | public: |
268 | // "Global" configuration state that can actually vary between modules. |
269 | |
270 | // Ignore all warnings: -w |
271 | unsigned IgnoreAllWarnings : 1; |
272 | |
273 | // Enable all warnings. |
274 | unsigned EnableAllWarnings : 1; |
275 | |
276 | // Treat warnings like errors. |
277 | unsigned WarningsAsErrors : 1; |
278 | |
279 | // Treat errors like fatal errors. |
280 | unsigned ErrorsAsFatal : 1; |
281 | |
282 | // Suppress warnings in system headers. |
283 | unsigned SuppressSystemWarnings : 1; |
284 | |
285 | // Map extensions to warnings or errors? |
286 | diag::Severity ExtBehavior = diag::Severity::Ignored; |
287 | |
288 | DiagState() |
289 | : IgnoreAllWarnings(false), EnableAllWarnings(false), |
290 | WarningsAsErrors(false), ErrorsAsFatal(false), |
291 | SuppressSystemWarnings(false) {} |
292 | |
293 | using iterator = llvm::DenseMap<unsigned, DiagnosticMapping>::iterator; |
294 | using const_iterator = |
295 | llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator; |
296 | |
297 | void setMapping(diag::kind Diag, DiagnosticMapping Info) { |
298 | DiagMap[Diag] = Info; |
299 | } |
300 | |
301 | DiagnosticMapping lookupMapping(diag::kind Diag) const { |
302 | return DiagMap.lookup(Diag); |
303 | } |
304 | |
305 | DiagnosticMapping &getOrAddMapping(diag::kind Diag); |
306 | |
307 | const_iterator begin() const { return DiagMap.begin(); } |
308 | const_iterator end() const { return DiagMap.end(); } |
309 | }; |
310 | |
311 | /// Keeps and automatically disposes all DiagStates that we create. |
312 | std::list<DiagState> DiagStates; |
313 | |
314 | /// A mapping from files to the diagnostic states for those files. Lazily |
315 | /// built on demand for files in which the diagnostic state has not changed. |
316 | class DiagStateMap { |
317 | public: |
318 | /// Add an initial diagnostic state. |
319 | void appendFirst(DiagState *State); |
320 | |
321 | /// Add a new latest state point. |
322 | void append(SourceManager &SrcMgr, SourceLocation Loc, DiagState *State); |
323 | |
324 | /// Look up the diagnostic state at a given source location. |
325 | DiagState *lookup(SourceManager &SrcMgr, SourceLocation Loc) const; |
326 | |
327 | /// Determine whether this map is empty. |
328 | bool empty() const { return Files.empty(); } |
329 | |
330 | /// Clear out this map. |
331 | void clear() { |
332 | Files.clear(); |
333 | FirstDiagState = CurDiagState = nullptr; |
334 | CurDiagStateLoc = SourceLocation(); |
335 | } |
336 | |
337 | /// Produce a debugging dump of the diagnostic state. |
338 | LLVM_DUMP_METHOD void dump(SourceManager &SrcMgr, |
339 | StringRef DiagName = StringRef()) const; |
340 | |
341 | /// Grab the most-recently-added state point. |
342 | DiagState *getCurDiagState() const { return CurDiagState; } |
343 | |
344 | /// Get the location at which a diagnostic state was last added. |
345 | SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; } |
346 | |
347 | private: |
348 | friend class ASTReader; |
349 | friend class ASTWriter; |
350 | |
351 | /// Represents a point in source where the diagnostic state was |
352 | /// modified because of a pragma. |
353 | /// |
354 | /// 'Loc' can be null if the point represents the diagnostic state |
355 | /// modifications done through the command-line. |
356 | struct DiagStatePoint { |
357 | DiagState *State; |
358 | unsigned Offset; |
359 | |
360 | DiagStatePoint(DiagState *State, unsigned Offset) |
361 | : State(State), Offset(Offset) {} |
362 | }; |
363 | |
364 | /// Description of the diagnostic states and state transitions for a |
365 | /// particular FileID. |
366 | struct File { |
367 | /// The diagnostic state for the parent file. This is strictly redundant, |
368 | /// as looking up the DecomposedIncludedLoc for the FileID in the Files |
369 | /// map would give us this, but we cache it here for performance. |
370 | File *Parent = nullptr; |
371 | |
372 | /// The offset of this file within its parent. |
373 | unsigned ParentOffset = 0; |
374 | |
375 | /// Whether this file has any local (not imported from an AST file) |
376 | /// diagnostic state transitions. |
377 | bool HasLocalTransitions = false; |
378 | |
379 | /// The points within the file where the state changes. There will always |
380 | /// be at least one of these (the state on entry to the file). |
381 | llvm::SmallVector<DiagStatePoint, 4> StateTransitions; |
382 | |
383 | DiagState *lookup(unsigned Offset) const; |
384 | }; |
385 | |
386 | /// The diagnostic states for each file. |
387 | mutable std::map<FileID, File> Files; |
388 | |
389 | /// The initial diagnostic state. |
390 | DiagState *FirstDiagState; |
391 | |
392 | /// The current diagnostic state. |
393 | DiagState *CurDiagState; |
394 | |
395 | /// The location at which the current diagnostic state was established. |
396 | SourceLocation CurDiagStateLoc; |
397 | |
398 | /// Get the diagnostic state information for a file. |
399 | File *getFile(SourceManager &SrcMgr, FileID ID) const; |
400 | }; |
401 | |
402 | DiagStateMap DiagStatesByLoc; |
403 | |
404 | /// Keeps the DiagState that was active during each diagnostic 'push' |
405 | /// so we can get back at it when we 'pop'. |
406 | std::vector<DiagState *> DiagStateOnPushStack; |
407 | |
408 | DiagState *GetCurDiagState() const { |
409 | return DiagStatesByLoc.getCurDiagState(); |
410 | } |
411 | |
412 | void PushDiagStatePoint(DiagState *State, SourceLocation L); |
413 | |
414 | /// Finds the DiagStatePoint that contains the diagnostic state of |
415 | /// the given source location. |
416 | DiagState *GetDiagStateForLoc(SourceLocation Loc) const { |
417 | return SourceMgr ? DiagStatesByLoc.lookup(*SourceMgr, Loc) |
418 | : DiagStatesByLoc.getCurDiagState(); |
419 | } |
420 | |
421 | /// Sticky flag set to \c true when an error is emitted. |
422 | bool ErrorOccurred; |
423 | |
424 | /// Sticky flag set to \c true when an "uncompilable error" occurs. |
425 | /// I.e. an error that was not upgraded from a warning by -Werror. |
426 | bool UncompilableErrorOccurred; |
427 | |
428 | /// Sticky flag set to \c true when a fatal error is emitted. |
429 | bool FatalErrorOccurred; |
430 | |
431 | /// Indicates that an unrecoverable error has occurred. |
432 | bool UnrecoverableErrorOccurred; |
433 | |
434 | /// Counts for DiagnosticErrorTrap to check whether an error occurred |
435 | /// during a parsing section, e.g. during parsing a function. |
436 | unsigned TrapNumErrorsOccurred; |
437 | unsigned TrapNumUnrecoverableErrorsOccurred; |
438 | |
439 | /// The level of the last diagnostic emitted. |
440 | /// |
441 | /// This is used to emit continuation diagnostics with the same level as the |
442 | /// diagnostic that they follow. |
443 | DiagnosticIDs::Level LastDiagLevel; |
444 | |
445 | /// Number of warnings reported |
446 | unsigned NumWarnings; |
447 | |
448 | /// Number of errors reported |
449 | unsigned NumErrors; |
450 | |
451 | /// A function pointer that converts an opaque diagnostic |
452 | /// argument to a strings. |
453 | /// |
454 | /// This takes the modifiers and argument that was present in the diagnostic. |
455 | /// |
456 | /// The PrevArgs array indicates the previous arguments formatted for this |
457 | /// diagnostic. Implementations of this function can use this information to |
458 | /// avoid redundancy across arguments. |
459 | /// |
460 | /// This is a hack to avoid a layering violation between libbasic and libsema. |
461 | using ArgToStringFnTy = void (*)( |
462 | ArgumentKind Kind, intptr_t Val, |
463 | StringRef Modifier, StringRef Argument, |
464 | ArrayRef<ArgumentValue> PrevArgs, |
465 | SmallVectorImpl<char> &Output, |
466 | void *Cookie, |
467 | ArrayRef<intptr_t> QualTypeVals); |
468 | |
469 | void *ArgToStringCookie = nullptr; |
470 | ArgToStringFnTy ArgToStringFn; |
471 | |
472 | /// ID of the "delayed" diagnostic, which is a (typically |
473 | /// fatal) diagnostic that had to be delayed because it was found |
474 | /// while emitting another diagnostic. |
475 | unsigned DelayedDiagID; |
476 | |
477 | /// First string argument for the delayed diagnostic. |
478 | std::string DelayedDiagArg1; |
479 | |
480 | /// Second string argument for the delayed diagnostic. |
481 | std::string DelayedDiagArg2; |
482 | |
483 | /// Third string argument for the delayed diagnostic. |
484 | std::string DelayedDiagArg3; |
485 | |
486 | /// Optional flag value. |
487 | /// |
488 | /// Some flags accept values, for instance: -Wframe-larger-than=<value> and |
489 | /// -Rpass=<value>. The content of this string is emitted after the flag name |
490 | /// and '='. |
491 | std::string FlagValue; |
492 | |
493 | public: |
494 | explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags, |
495 | IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, |
496 | DiagnosticConsumer *client = nullptr, |
497 | bool ShouldOwnClient = true); |
498 | DiagnosticsEngine(const DiagnosticsEngine &) = delete; |
499 | DiagnosticsEngine &operator=(const DiagnosticsEngine &) = delete; |
500 | ~DiagnosticsEngine(); |
501 | |
502 | LLVM_DUMP_METHOD void dump() const; |
503 | LLVM_DUMP_METHOD void dump(StringRef DiagName) const; |
504 | |
505 | const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const { |
506 | return Diags; |
507 | } |
508 | |
509 | /// Retrieve the diagnostic options. |
510 | DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; } |
511 | |
512 | using diag_mapping_range = llvm::iterator_range<DiagState::const_iterator>; |
513 | |
514 | /// Get the current set of diagnostic mappings. |
515 | diag_mapping_range getDiagnosticMappings() const { |
516 | const DiagState &DS = *GetCurDiagState(); |
517 | return diag_mapping_range(DS.begin(), DS.end()); |
518 | } |
519 | |
520 | DiagnosticConsumer *getClient() { return Client; } |
521 | const DiagnosticConsumer *getClient() const { return Client; } |
522 | |
523 | /// Determine whether this \c DiagnosticsEngine object own its client. |
524 | bool ownsClient() const { return Owner != nullptr; } |
525 | |
526 | /// Return the current diagnostic client along with ownership of that |
527 | /// client. |
528 | std::unique_ptr<DiagnosticConsumer> takeClient() { return std::move(Owner); } |
529 | |
530 | bool hasSourceManager() const { return SourceMgr != nullptr; } |
531 | |
532 | SourceManager &getSourceManager() const { |
533 | assert(SourceMgr && "SourceManager not set!" ); |
534 | return *SourceMgr; |
535 | } |
536 | |
537 | void setSourceManager(SourceManager *SrcMgr) { |
538 | assert(DiagStatesByLoc.empty() && |
539 | "Leftover diag state from a different SourceManager." ); |
540 | SourceMgr = SrcMgr; |
541 | } |
542 | |
543 | //===--------------------------------------------------------------------===// |
544 | // DiagnosticsEngine characterization methods, used by a client to customize |
545 | // how diagnostics are emitted. |
546 | // |
547 | |
548 | /// Copies the current DiagMappings and pushes the new copy |
549 | /// onto the top of the stack. |
550 | void pushMappings(SourceLocation Loc); |
551 | |
552 | /// Pops the current DiagMappings off the top of the stack, |
553 | /// causing the new top of the stack to be the active mappings. |
554 | /// |
555 | /// \returns \c true if the pop happens, \c false if there is only one |
556 | /// DiagMapping on the stack. |
557 | bool popMappings(SourceLocation Loc); |
558 | |
559 | /// Set the diagnostic client associated with this diagnostic object. |
560 | /// |
561 | /// \param ShouldOwnClient true if the diagnostic object should take |
562 | /// ownership of \c client. |
563 | void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true); |
564 | |
565 | /// Specify a limit for the number of errors we should |
566 | /// emit before giving up. |
567 | /// |
568 | /// Zero disables the limit. |
569 | void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; } |
570 | |
571 | /// Specify the maximum number of template instantiation |
572 | /// notes to emit along with a given diagnostic. |
573 | void setTemplateBacktraceLimit(unsigned Limit) { |
574 | TemplateBacktraceLimit = Limit; |
575 | } |
576 | |
577 | /// Retrieve the maximum number of template instantiation |
578 | /// notes to emit along with a given diagnostic. |
579 | unsigned getTemplateBacktraceLimit() const { |
580 | return TemplateBacktraceLimit; |
581 | } |
582 | |
583 | /// Specify the maximum number of constexpr evaluation |
584 | /// notes to emit along with a given diagnostic. |
585 | void setConstexprBacktraceLimit(unsigned Limit) { |
586 | ConstexprBacktraceLimit = Limit; |
587 | } |
588 | |
589 | /// Retrieve the maximum number of constexpr evaluation |
590 | /// notes to emit along with a given diagnostic. |
591 | unsigned getConstexprBacktraceLimit() const { |
592 | return ConstexprBacktraceLimit; |
593 | } |
594 | |
595 | /// When set to true, any unmapped warnings are ignored. |
596 | /// |
597 | /// If this and WarningsAsErrors are both set, then this one wins. |
598 | void setIgnoreAllWarnings(bool Val) { |
599 | GetCurDiagState()->IgnoreAllWarnings = Val; |
600 | } |
601 | bool getIgnoreAllWarnings() const { |
602 | return GetCurDiagState()->IgnoreAllWarnings; |
603 | } |
604 | |
605 | /// When set to true, any unmapped ignored warnings are no longer |
606 | /// ignored. |
607 | /// |
608 | /// If this and IgnoreAllWarnings are both set, then that one wins. |
609 | void setEnableAllWarnings(bool Val) { |
610 | GetCurDiagState()->EnableAllWarnings = Val; |
611 | } |
612 | bool getEnableAllWarnings() const { |
613 | return GetCurDiagState()->EnableAllWarnings; |
614 | } |
615 | |
616 | /// When set to true, any warnings reported are issued as errors. |
617 | void setWarningsAsErrors(bool Val) { |
618 | GetCurDiagState()->WarningsAsErrors = Val; |
619 | } |
620 | bool getWarningsAsErrors() const { |
621 | return GetCurDiagState()->WarningsAsErrors; |
622 | } |
623 | |
624 | /// When set to true, any error reported is made a fatal error. |
625 | void setErrorsAsFatal(bool Val) { GetCurDiagState()->ErrorsAsFatal = Val; } |
626 | bool getErrorsAsFatal() const { return GetCurDiagState()->ErrorsAsFatal; } |
627 | |
628 | /// \brief When set to true, any fatal error reported is made an error. |
629 | /// |
630 | /// This setting takes precedence over the setErrorsAsFatal setting above. |
631 | void setFatalsAsError(bool Val) { FatalsAsError = Val; } |
632 | bool getFatalsAsError() const { return FatalsAsError; } |
633 | |
634 | /// When set to true mask warnings that come from system headers. |
635 | void setSuppressSystemWarnings(bool Val) { |
636 | GetCurDiagState()->SuppressSystemWarnings = Val; |
637 | } |
638 | bool getSuppressSystemWarnings() const { |
639 | return GetCurDiagState()->SuppressSystemWarnings; |
640 | } |
641 | |
642 | /// Suppress all diagnostics, to silence the front end when we |
643 | /// know that we don't want any more diagnostics to be passed along to the |
644 | /// client |
645 | void setSuppressAllDiagnostics(bool Val) { SuppressAllDiagnostics = Val; } |
646 | bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; } |
647 | |
648 | /// Set type eliding, to skip outputting same types occurring in |
649 | /// template types. |
650 | void setElideType(bool Val) { ElideType = Val; } |
651 | bool getElideType() { return ElideType; } |
652 | |
653 | /// Set tree printing, to outputting the template difference in a |
654 | /// tree format. |
655 | void setPrintTemplateTree(bool Val) { PrintTemplateTree = Val; } |
656 | bool getPrintTemplateTree() { return PrintTemplateTree; } |
657 | |
658 | /// Set color printing, so the type diffing will inject color markers |
659 | /// into the output. |
660 | void setShowColors(bool Val) { ShowColors = Val; } |
661 | bool getShowColors() { return ShowColors; } |
662 | |
663 | /// Specify which overload candidates to show when overload resolution |
664 | /// fails. |
665 | /// |
666 | /// By default, we show all candidates. |
667 | void setShowOverloads(OverloadsShown Val) { |
668 | ShowOverloads = Val; |
669 | } |
670 | OverloadsShown getShowOverloads() const { return ShowOverloads; } |
671 | |
672 | /// Pretend that the last diagnostic issued was ignored, so any |
673 | /// subsequent notes will be suppressed, or restore a prior ignoring |
674 | /// state after ignoring some diagnostics and their notes, possibly in |
675 | /// the middle of another diagnostic. |
676 | /// |
677 | /// This can be used by clients who suppress diagnostics themselves. |
678 | void setLastDiagnosticIgnored(bool Ignored) { |
679 | if (LastDiagLevel == DiagnosticIDs::Fatal) |
680 | FatalErrorOccurred = true; |
681 | LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning; |
682 | } |
683 | |
684 | /// Determine whether the previous diagnostic was ignored. This can |
685 | /// be used by clients that want to determine whether notes attached to a |
686 | /// diagnostic will be suppressed. |
687 | bool isLastDiagnosticIgnored() const { |
688 | return LastDiagLevel == DiagnosticIDs::Ignored; |
689 | } |
690 | |
691 | /// Controls whether otherwise-unmapped extension diagnostics are |
692 | /// mapped onto ignore/warning/error. |
693 | /// |
694 | /// This corresponds to the GCC -pedantic and -pedantic-errors option. |
695 | void setExtensionHandlingBehavior(diag::Severity H) { |
696 | GetCurDiagState()->ExtBehavior = H; |
697 | } |
698 | diag::Severity getExtensionHandlingBehavior() const { |
699 | return GetCurDiagState()->ExtBehavior; |
700 | } |
701 | |
702 | /// Counter bumped when an __extension__ block is/ encountered. |
703 | /// |
704 | /// When non-zero, all extension diagnostics are entirely silenced, no |
705 | /// matter how they are mapped. |
706 | void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; } |
707 | void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; } |
708 | bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; } |
709 | |
710 | /// This allows the client to specify that certain warnings are |
711 | /// ignored. |
712 | /// |
713 | /// Notes can never be mapped, errors can only be mapped to fatal, and |
714 | /// WARNINGs and EXTENSIONs can be mapped arbitrarily. |
715 | /// |
716 | /// \param Loc The source location that this change of diagnostic state should |
717 | /// take affect. It can be null if we are setting the latest state. |
718 | void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc); |
719 | |
720 | /// Change an entire diagnostic group (e.g. "unknown-pragmas") to |
721 | /// have the specified mapping. |
722 | /// |
723 | /// \returns true (and ignores the request) if "Group" was unknown, false |
724 | /// otherwise. |
725 | /// |
726 | /// \param Flavor The flavor of group to affect. -Rfoo does not affect the |
727 | /// state of the -Wfoo group and vice versa. |
728 | /// |
729 | /// \param Loc The source location that this change of diagnostic state should |
730 | /// take affect. It can be null if we are setting the state from command-line. |
731 | bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group, |
732 | diag::Severity Map, |
733 | SourceLocation Loc = SourceLocation()); |
734 | |
735 | /// Set the warning-as-error flag for the given diagnostic group. |
736 | /// |
737 | /// This function always only operates on the current diagnostic state. |
738 | /// |
739 | /// \returns True if the given group is unknown, false otherwise. |
740 | bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled); |
741 | |
742 | /// Set the error-as-fatal flag for the given diagnostic group. |
743 | /// |
744 | /// This function always only operates on the current diagnostic state. |
745 | /// |
746 | /// \returns True if the given group is unknown, false otherwise. |
747 | bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled); |
748 | |
749 | /// Add the specified mapping to all diagnostics of the specified |
750 | /// flavor. |
751 | /// |
752 | /// Mainly to be used by -Wno-everything to disable all warnings but allow |
753 | /// subsequent -W options to enable specific warnings. |
754 | void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map, |
755 | SourceLocation Loc = SourceLocation()); |
756 | |
757 | bool hasErrorOccurred() const { return ErrorOccurred; } |
758 | |
759 | /// Errors that actually prevent compilation, not those that are |
760 | /// upgraded from a warning by -Werror. |
761 | bool hasUncompilableErrorOccurred() const { |
762 | return UncompilableErrorOccurred; |
763 | } |
764 | bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } |
765 | |
766 | /// Determine whether any kind of unrecoverable error has occurred. |
767 | bool hasUnrecoverableErrorOccurred() const { |
768 | return FatalErrorOccurred || UnrecoverableErrorOccurred; |
769 | } |
770 | |
771 | unsigned getNumWarnings() const { return NumWarnings; } |
772 | |
773 | void setNumWarnings(unsigned NumWarnings) { |
774 | this->NumWarnings = NumWarnings; |
775 | } |
776 | |
777 | /// Return an ID for a diagnostic with the specified format string and |
778 | /// level. |
779 | /// |
780 | /// If this is the first request for this diagnostic, it is registered and |
781 | /// created, otherwise the existing ID is returned. |
782 | /// |
783 | /// \param FormatString A fixed diagnostic format string that will be hashed |
784 | /// and mapped to a unique DiagID. |
785 | template <unsigned N> |
786 | unsigned getCustomDiagID(Level L, const char (&FormatString)[N]) { |
787 | return Diags->getCustomDiagID((DiagnosticIDs::Level)L, |
788 | StringRef(FormatString, N - 1)); |
789 | } |
790 | |
791 | /// Converts a diagnostic argument (as an intptr_t) into the string |
792 | /// that represents it. |
793 | void ConvertArgToString(ArgumentKind Kind, intptr_t Val, |
794 | StringRef Modifier, StringRef Argument, |
795 | ArrayRef<ArgumentValue> PrevArgs, |
796 | SmallVectorImpl<char> &Output, |
797 | ArrayRef<intptr_t> QualTypeVals) const { |
798 | ArgToStringFn(Kind, Val, Modifier, Argument, PrevArgs, Output, |
799 | ArgToStringCookie, QualTypeVals); |
800 | } |
801 | |
802 | void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { |
803 | ArgToStringFn = Fn; |
804 | ArgToStringCookie = Cookie; |
805 | } |
806 | |
807 | /// Note that the prior diagnostic was emitted by some other |
808 | /// \c DiagnosticsEngine, and we may be attaching a note to that diagnostic. |
809 | void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) { |
810 | LastDiagLevel = Other.LastDiagLevel; |
811 | } |
812 | |
813 | /// Reset the state of the diagnostic object to its initial |
814 | /// configuration. |
815 | void Reset(); |
816 | |
817 | //===--------------------------------------------------------------------===// |
818 | // DiagnosticsEngine classification and reporting interfaces. |
819 | // |
820 | |
821 | /// Determine whether the diagnostic is known to be ignored. |
822 | /// |
823 | /// This can be used to opportunistically avoid expensive checks when it's |
824 | /// known for certain that the diagnostic has been suppressed at the |
825 | /// specified location \p Loc. |
826 | /// |
827 | /// \param Loc The source location we are interested in finding out the |
828 | /// diagnostic state. Can be null in order to query the latest state. |
829 | bool isIgnored(unsigned DiagID, SourceLocation Loc) const { |
830 | return Diags->getDiagnosticSeverity(DiagID, Loc, *this) == |
831 | diag::Severity::Ignored; |
832 | } |
833 | |
834 | /// Based on the way the client configured the DiagnosticsEngine |
835 | /// object, classify the specified diagnostic ID into a Level, consumable by |
836 | /// the DiagnosticConsumer. |
837 | /// |
838 | /// To preserve invariant assumptions, this function should not be used to |
839 | /// influence parse or semantic analysis actions. Instead consider using |
840 | /// \c isIgnored(). |
841 | /// |
842 | /// \param Loc The source location we are interested in finding out the |
843 | /// diagnostic state. Can be null in order to query the latest state. |
844 | Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const { |
845 | return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this); |
846 | } |
847 | |
848 | /// Issue the message to the client. |
849 | /// |
850 | /// This actually returns an instance of DiagnosticBuilder which emits the |
851 | /// diagnostics (through @c ProcessDiag) when it is destroyed. |
852 | /// |
853 | /// \param DiagID A member of the @c diag::kind enum. |
854 | /// \param Loc Represents the source location associated with the diagnostic, |
855 | /// which can be an invalid location if no position information is available. |
856 | inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID); |
857 | inline DiagnosticBuilder Report(unsigned DiagID); |
858 | |
859 | void Report(const StoredDiagnostic &storedDiag); |
860 | |
861 | /// Determine whethere there is already a diagnostic in flight. |
862 | bool isDiagnosticInFlight() const { |
863 | return CurDiagID != std::numeric_limits<unsigned>::max(); |
864 | } |
865 | |
866 | /// Set the "delayed" diagnostic that will be emitted once |
867 | /// the current diagnostic completes. |
868 | /// |
869 | /// If a diagnostic is already in-flight but the front end must |
870 | /// report a problem (e.g., with an inconsistent file system |
871 | /// state), this routine sets a "delayed" diagnostic that will be |
872 | /// emitted after the current diagnostic completes. This should |
873 | /// only be used for fatal errors detected at inconvenient |
874 | /// times. If emitting a delayed diagnostic causes a second delayed |
875 | /// diagnostic to be introduced, that second delayed diagnostic |
876 | /// will be ignored. |
877 | /// |
878 | /// \param DiagID The ID of the diagnostic being delayed. |
879 | /// |
880 | /// \param Arg1 A string argument that will be provided to the |
881 | /// diagnostic. A copy of this string will be stored in the |
882 | /// DiagnosticsEngine object itself. |
883 | /// |
884 | /// \param Arg2 A string argument that will be provided to the |
885 | /// diagnostic. A copy of this string will be stored in the |
886 | /// DiagnosticsEngine object itself. |
887 | /// |
888 | /// \param Arg3 A string argument that will be provided to the |
889 | /// diagnostic. A copy of this string will be stored in the |
890 | /// DiagnosticsEngine object itself. |
891 | void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "" , |
892 | StringRef Arg2 = "" , StringRef Arg3 = "" ); |
893 | |
894 | /// Clear out the current diagnostic. |
895 | void Clear() { CurDiagID = std::numeric_limits<unsigned>::max(); } |
896 | |
897 | /// Return the value associated with this diagnostic flag. |
898 | StringRef getFlagValue() const { return FlagValue; } |
899 | |
900 | private: |
901 | // This is private state used by DiagnosticBuilder. We put it here instead of |
902 | // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight |
903 | // object. This implementation choice means that we can only have one |
904 | // diagnostic "in flight" at a time, but this seems to be a reasonable |
905 | // tradeoff to keep these objects small. Assertions verify that only one |
906 | // diagnostic is in flight at a time. |
907 | friend class Diagnostic; |
908 | friend class DiagnosticBuilder; |
909 | friend class DiagnosticErrorTrap; |
910 | friend class DiagnosticIDs; |
911 | friend class PartialDiagnostic; |
912 | |
913 | /// Report the delayed diagnostic. |
914 | void ReportDelayed(); |
915 | |
916 | /// The location of the current diagnostic that is in flight. |
917 | SourceLocation CurDiagLoc; |
918 | |
919 | /// The ID of the current diagnostic that is in flight. |
920 | /// |
921 | /// This is set to std::numeric_limits<unsigned>::max() when there is no |
922 | /// diagnostic in flight. |
923 | unsigned CurDiagID; |
924 | |
925 | enum { |
926 | /// The maximum number of arguments we can hold. |
927 | /// |
928 | /// We currently only support up to 10 arguments (%0-%9). A single |
929 | /// diagnostic with more than that almost certainly has to be simplified |
930 | /// anyway. |
931 | MaxArguments = 10, |
932 | }; |
933 | |
934 | /// The number of entries in Arguments. |
935 | signed char NumDiagArgs; |
936 | |
937 | /// Specifies whether an argument is in DiagArgumentsStr or |
938 | /// in DiagArguments. |
939 | /// |
940 | /// This is an array of ArgumentKind::ArgumentKind enum values, one for each |
941 | /// argument. |
942 | unsigned char DiagArgumentsKind[MaxArguments]; |
943 | |
944 | /// Holds the values of each string argument for the current |
945 | /// diagnostic. |
946 | /// |
947 | /// This is only used when the corresponding ArgumentKind is ak_std_string. |
948 | std::string DiagArgumentsStr[MaxArguments]; |
949 | |
950 | /// The values for the various substitution positions. |
951 | /// |
952 | /// This is used when the argument is not an std::string. The specific |
953 | /// value is mangled into an intptr_t and the interpretation depends on |
954 | /// exactly what sort of argument kind it is. |
955 | intptr_t DiagArgumentsVal[MaxArguments]; |
956 | |
957 | /// The list of ranges added to this diagnostic. |
958 | SmallVector<CharSourceRange, 8> DiagRanges; |
959 | |
960 | /// If valid, provides a hint with some code to insert, remove, |
961 | /// or modify at a particular position. |
962 | SmallVector<FixItHint, 8> DiagFixItHints; |
963 | |
964 | DiagnosticMapping makeUserMapping(diag::Severity Map, SourceLocation L) { |
965 | bool isPragma = L.isValid(); |
966 | DiagnosticMapping Mapping = |
967 | DiagnosticMapping::Make(Map, /*IsUser=*/true, isPragma); |
968 | |
969 | // If this is a pragma mapping, then set the diagnostic mapping flags so |
970 | // that we override command line options. |
971 | if (isPragma) { |
972 | Mapping.setNoWarningAsError(true); |
973 | Mapping.setNoErrorAsFatal(true); |
974 | } |
975 | |
976 | return Mapping; |
977 | } |
978 | |
979 | /// Used to report a diagnostic that is finally fully formed. |
980 | /// |
981 | /// \returns true if the diagnostic was emitted, false if it was suppressed. |
982 | bool ProcessDiag() { |
983 | return Diags->ProcessDiag(*this); |
984 | } |
985 | |
986 | /// @name Diagnostic Emission |
987 | /// @{ |
988 | protected: |
989 | friend class ASTReader; |
990 | friend class ASTWriter; |
991 | |
992 | // Sema requires access to the following functions because the current design |
993 | // of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to |
994 | // access us directly to ensure we minimize the emitted code for the common |
995 | // Sema::Diag() patterns. |
996 | friend class Sema; |
997 | |
998 | /// Emit the current diagnostic and clear the diagnostic state. |
999 | /// |
1000 | /// \param Force Emit the diagnostic regardless of suppression settings. |
1001 | bool EmitCurrentDiagnostic(bool Force = false); |
1002 | |
1003 | unsigned getCurrentDiagID() const { return CurDiagID; } |
1004 | |
1005 | SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; } |
1006 | |
1007 | /// @} |
1008 | }; |
1009 | |
1010 | /// RAII class that determines when any errors have occurred |
1011 | /// between the time the instance was created and the time it was |
1012 | /// queried. |
1013 | class DiagnosticErrorTrap { |
1014 | DiagnosticsEngine &Diag; |
1015 | unsigned NumErrors; |
1016 | unsigned NumUnrecoverableErrors; |
1017 | |
1018 | public: |
1019 | explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag) |
1020 | : Diag(Diag) { reset(); } |
1021 | |
1022 | /// Determine whether any errors have occurred since this |
1023 | /// object instance was created. |
1024 | bool hasErrorOccurred() const { |
1025 | return Diag.TrapNumErrorsOccurred > NumErrors; |
1026 | } |
1027 | |
1028 | /// Determine whether any unrecoverable errors have occurred since this |
1029 | /// object instance was created. |
1030 | bool hasUnrecoverableErrorOccurred() const { |
1031 | return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors; |
1032 | } |
1033 | |
1034 | /// Set to initial state of "no errors occurred". |
1035 | void reset() { |
1036 | NumErrors = Diag.TrapNumErrorsOccurred; |
1037 | NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred; |
1038 | } |
1039 | }; |
1040 | |
1041 | //===----------------------------------------------------------------------===// |
1042 | // DiagnosticBuilder |
1043 | //===----------------------------------------------------------------------===// |
1044 | |
1045 | /// A little helper class used to produce diagnostics. |
1046 | /// |
1047 | /// This is constructed by the DiagnosticsEngine::Report method, and |
1048 | /// allows insertion of extra information (arguments and source ranges) into |
1049 | /// the currently "in flight" diagnostic. When the temporary for the builder |
1050 | /// is destroyed, the diagnostic is issued. |
1051 | /// |
1052 | /// Note that many of these will be created as temporary objects (many call |
1053 | /// sites), so we want them to be small and we never want their address taken. |
1054 | /// This ensures that compilers with somewhat reasonable optimizers will promote |
1055 | /// the common fields to registers, eliminating increments of the NumArgs field, |
1056 | /// for example. |
1057 | class DiagnosticBuilder { |
1058 | friend class DiagnosticsEngine; |
1059 | friend class PartialDiagnostic; |
1060 | |
1061 | mutable DiagnosticsEngine *DiagObj = nullptr; |
1062 | mutable unsigned NumArgs = 0; |
1063 | |
1064 | /// Status variable indicating if this diagnostic is still active. |
1065 | /// |
1066 | // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)), |
1067 | // but LLVM is not currently smart enough to eliminate the null check that |
1068 | // Emit() would end up with if we used that as our status variable. |
1069 | mutable bool IsActive = false; |
1070 | |
1071 | /// Flag indicating that this diagnostic is being emitted via a |
1072 | /// call to ForceEmit. |
1073 | mutable bool IsForceEmit = false; |
1074 | |
1075 | DiagnosticBuilder() = default; |
1076 | |
1077 | explicit DiagnosticBuilder(DiagnosticsEngine *diagObj) |
1078 | : DiagObj(diagObj), IsActive(true) { |
1079 | assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!" ); |
1080 | diagObj->DiagRanges.clear(); |
1081 | diagObj->DiagFixItHints.clear(); |
1082 | } |
1083 | |
1084 | protected: |
1085 | void FlushCounts() { |
1086 | DiagObj->NumDiagArgs = NumArgs; |
1087 | } |
1088 | |
1089 | /// Clear out the current diagnostic. |
1090 | void Clear() const { |
1091 | DiagObj = nullptr; |
1092 | IsActive = false; |
1093 | IsForceEmit = false; |
1094 | } |
1095 | |
1096 | /// Determine whether this diagnostic is still active. |
1097 | bool isActive() const { return IsActive; } |
1098 | |
1099 | /// Force the diagnostic builder to emit the diagnostic now. |
1100 | /// |
1101 | /// Once this function has been called, the DiagnosticBuilder object |
1102 | /// should not be used again before it is destroyed. |
1103 | /// |
1104 | /// \returns true if a diagnostic was emitted, false if the |
1105 | /// diagnostic was suppressed. |
1106 | bool Emit() { |
1107 | // If this diagnostic is inactive, then its soul was stolen by the copy ctor |
1108 | // (or by a subclass, as in SemaDiagnosticBuilder). |
1109 | if (!isActive()) return false; |
1110 | |
1111 | // When emitting diagnostics, we set the final argument count into |
1112 | // the DiagnosticsEngine object. |
1113 | FlushCounts(); |
1114 | |
1115 | // Process the diagnostic. |
1116 | bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit); |
1117 | |
1118 | // This diagnostic is dead. |
1119 | Clear(); |
1120 | |
1121 | return Result; |
1122 | } |
1123 | |
1124 | public: |
1125 | /// Copy constructor. When copied, this "takes" the diagnostic info from the |
1126 | /// input and neuters it. |
1127 | DiagnosticBuilder(const DiagnosticBuilder &D) { |
1128 | DiagObj = D.DiagObj; |
1129 | IsActive = D.IsActive; |
1130 | IsForceEmit = D.IsForceEmit; |
1131 | D.Clear(); |
1132 | NumArgs = D.NumArgs; |
1133 | } |
1134 | |
1135 | DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete; |
1136 | |
1137 | /// Emits the diagnostic. |
1138 | ~DiagnosticBuilder() { |
1139 | Emit(); |
1140 | } |
1141 | |
1142 | /// Forces the diagnostic to be emitted. |
1143 | const DiagnosticBuilder &setForceEmit() const { |
1144 | IsForceEmit = true; |
1145 | return *this; |
1146 | } |
1147 | |
1148 | /// Conversion of DiagnosticBuilder to bool always returns \c true. |
1149 | /// |
1150 | /// This allows is to be used in boolean error contexts (where \c true is |
1151 | /// used to indicate that an error has occurred), like: |
1152 | /// \code |
1153 | /// return Diag(...); |
1154 | /// \endcode |
1155 | operator bool() const { return true; } |
1156 | |
1157 | void AddString(StringRef S) const { |
1158 | assert(isActive() && "Clients must not add to cleared diagnostic!" ); |
1159 | assert(NumArgs < DiagnosticsEngine::MaxArguments && |
1160 | "Too many arguments to diagnostic!" ); |
1161 | DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string; |
1162 | DiagObj->DiagArgumentsStr[NumArgs++] = std::string(S); |
1163 | } |
1164 | |
1165 | void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const { |
1166 | assert(isActive() && "Clients must not add to cleared diagnostic!" ); |
1167 | assert(NumArgs < DiagnosticsEngine::MaxArguments && |
1168 | "Too many arguments to diagnostic!" ); |
1169 | DiagObj->DiagArgumentsKind[NumArgs] = Kind; |
1170 | DiagObj->DiagArgumentsVal[NumArgs++] = V; |
1171 | } |
1172 | |
1173 | void AddSourceRange(const CharSourceRange &R) const { |
1174 | assert(isActive() && "Clients must not add to cleared diagnostic!" ); |
1175 | DiagObj->DiagRanges.push_back(R); |
1176 | } |
1177 | |
1178 | void AddFixItHint(const FixItHint &Hint) const { |
1179 | assert(isActive() && "Clients must not add to cleared diagnostic!" ); |
1180 | if (!Hint.isNull()) |
1181 | DiagObj->DiagFixItHints.push_back(Hint); |
1182 | } |
1183 | |
1184 | void addFlagValue(StringRef V) const { DiagObj->FlagValue = std::string(V); } |
1185 | }; |
1186 | |
1187 | struct AddFlagValue { |
1188 | StringRef Val; |
1189 | |
1190 | explicit AddFlagValue(StringRef V) : Val(V) {} |
1191 | }; |
1192 | |
1193 | /// Register a value for the flag in the current diagnostic. This |
1194 | /// value will be shown as the suffix "=value" after the flag name. It is |
1195 | /// useful in cases where the diagnostic flag accepts values (e.g., |
1196 | /// -Rpass or -Wframe-larger-than). |
1197 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1198 | const AddFlagValue V) { |
1199 | DB.addFlagValue(V.Val); |
1200 | return DB; |
1201 | } |
1202 | |
1203 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1204 | StringRef S) { |
1205 | DB.AddString(S); |
1206 | return DB; |
1207 | } |
1208 | |
1209 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1210 | const char *Str) { |
1211 | DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str), |
1212 | DiagnosticsEngine::ak_c_string); |
1213 | return DB; |
1214 | } |
1215 | |
1216 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) { |
1217 | DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); |
1218 | return DB; |
1219 | } |
1220 | |
1221 | // We use enable_if here to prevent that this overload is selected for |
1222 | // pointers or other arguments that are implicitly convertible to bool. |
1223 | template <typename T> |
1224 | inline std::enable_if_t<std::is_same<T, bool>::value, const DiagnosticBuilder &> |
1225 | operator<<(const DiagnosticBuilder &DB, T I) { |
1226 | DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); |
1227 | return DB; |
1228 | } |
1229 | |
1230 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1231 | unsigned I) { |
1232 | DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint); |
1233 | return DB; |
1234 | } |
1235 | |
1236 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1237 | tok::TokenKind I) { |
1238 | DB.AddTaggedVal(static_cast<unsigned>(I), DiagnosticsEngine::ak_tokenkind); |
1239 | return DB; |
1240 | } |
1241 | |
1242 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1243 | const IdentifierInfo *II) { |
1244 | DB.AddTaggedVal(reinterpret_cast<intptr_t>(II), |
1245 | DiagnosticsEngine::ak_identifierinfo); |
1246 | return DB; |
1247 | } |
1248 | |
1249 | // Adds a DeclContext to the diagnostic. The enable_if template magic is here |
1250 | // so that we only match those arguments that are (statically) DeclContexts; |
1251 | // other arguments that derive from DeclContext (e.g., RecordDecls) will not |
1252 | // match. |
1253 | template <typename T> |
1254 | inline std::enable_if_t< |
1255 | std::is_same<std::remove_const_t<T>, DeclContext>::value, |
1256 | const DiagnosticBuilder &> |
1257 | operator<<(const DiagnosticBuilder &DB, T *DC) { |
1258 | DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC), |
1259 | DiagnosticsEngine::ak_declcontext); |
1260 | return DB; |
1261 | } |
1262 | |
1263 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1264 | SourceRange R) { |
1265 | DB.AddSourceRange(CharSourceRange::getTokenRange(R)); |
1266 | return DB; |
1267 | } |
1268 | |
1269 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1270 | ArrayRef<SourceRange> Ranges) { |
1271 | for (SourceRange R : Ranges) |
1272 | DB.AddSourceRange(CharSourceRange::getTokenRange(R)); |
1273 | return DB; |
1274 | } |
1275 | |
1276 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1277 | const CharSourceRange &R) { |
1278 | DB.AddSourceRange(R); |
1279 | return DB; |
1280 | } |
1281 | |
1282 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1283 | const FixItHint &Hint) { |
1284 | DB.AddFixItHint(Hint); |
1285 | return DB; |
1286 | } |
1287 | |
1288 | inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1289 | ArrayRef<FixItHint> Hints) { |
1290 | for (const FixItHint &Hint : Hints) |
1291 | DB.AddFixItHint(Hint); |
1292 | return DB; |
1293 | } |
1294 | |
1295 | inline const DiagnosticBuilder & |
1296 | operator<<(const DiagnosticBuilder &DB, |
1297 | const llvm::Optional<SourceRange> &Opt) { |
1298 | if (Opt) |
1299 | DB << *Opt; |
1300 | return DB; |
1301 | } |
1302 | |
1303 | inline const DiagnosticBuilder & |
1304 | operator<<(const DiagnosticBuilder &DB, |
1305 | const llvm::Optional<CharSourceRange> &Opt) { |
1306 | if (Opt) |
1307 | DB << *Opt; |
1308 | return DB; |
1309 | } |
1310 | |
1311 | inline const DiagnosticBuilder & |
1312 | operator<<(const DiagnosticBuilder &DB, const llvm::Optional<FixItHint> &Opt) { |
1313 | if (Opt) |
1314 | DB << *Opt; |
1315 | return DB; |
1316 | } |
1317 | |
1318 | /// A nullability kind paired with a bit indicating whether it used a |
1319 | /// context-sensitive keyword. |
1320 | using DiagNullabilityKind = std::pair<NullabilityKind, bool>; |
1321 | |
1322 | const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1323 | DiagNullabilityKind nullability); |
1324 | |
1325 | inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc, |
1326 | unsigned DiagID) { |
1327 | assert(CurDiagID == std::numeric_limits<unsigned>::max() && |
1328 | "Multiple diagnostics in flight at once!" ); |
1329 | CurDiagLoc = Loc; |
1330 | CurDiagID = DiagID; |
1331 | FlagValue.clear(); |
1332 | return DiagnosticBuilder(this); |
1333 | } |
1334 | |
1335 | const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, |
1336 | llvm::Error &&E); |
1337 | |
1338 | inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) { |
1339 | return Report(SourceLocation(), DiagID); |
1340 | } |
1341 | |
1342 | //===----------------------------------------------------------------------===// |
1343 | // Diagnostic |
1344 | //===----------------------------------------------------------------------===// |
1345 | |
1346 | /// A little helper class (which is basically a smart pointer that forwards |
1347 | /// info from DiagnosticsEngine) that allows clients to enquire about the |
1348 | /// currently in-flight diagnostic. |
1349 | class Diagnostic { |
1350 | const DiagnosticsEngine *DiagObj; |
1351 | StringRef StoredDiagMessage; |
1352 | |
1353 | public: |
1354 | explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {} |
1355 | Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage) |
1356 | : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {} |
1357 | |
1358 | const DiagnosticsEngine *getDiags() const { return DiagObj; } |
1359 | unsigned getID() const { return DiagObj->CurDiagID; } |
1360 | const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; } |
1361 | bool hasSourceManager() const { return DiagObj->hasSourceManager(); } |
1362 | SourceManager &getSourceManager() const { return DiagObj->getSourceManager();} |
1363 | |
1364 | unsigned getNumArgs() const { return DiagObj->NumDiagArgs; } |
1365 | |
1366 | /// Return the kind of the specified index. |
1367 | /// |
1368 | /// Based on the kind of argument, the accessors below can be used to get |
1369 | /// the value. |
1370 | /// |
1371 | /// \pre Idx < getNumArgs() |
1372 | DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const { |
1373 | assert(Idx < getNumArgs() && "Argument index out of range!" ); |
1374 | return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx]; |
1375 | } |
1376 | |
1377 | /// Return the provided argument string specified by \p Idx. |
1378 | /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string |
1379 | const std::string &getArgStdStr(unsigned Idx) const { |
1380 | assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string && |
1381 | "invalid argument accessor!" ); |
1382 | return DiagObj->DiagArgumentsStr[Idx]; |
1383 | } |
1384 | |
1385 | /// Return the specified C string argument. |
1386 | /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string |
1387 | const char *getArgCStr(unsigned Idx) const { |
1388 | assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string && |
1389 | "invalid argument accessor!" ); |
1390 | return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]); |
1391 | } |
1392 | |
1393 | /// Return the specified signed integer argument. |
1394 | /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint |
1395 | int getArgSInt(unsigned Idx) const { |
1396 | assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint && |
1397 | "invalid argument accessor!" ); |
1398 | return (int)DiagObj->DiagArgumentsVal[Idx]; |
1399 | } |
1400 | |
1401 | /// Return the specified unsigned integer argument. |
1402 | /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint |
1403 | unsigned getArgUInt(unsigned Idx) const { |
1404 | assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint && |
1405 | "invalid argument accessor!" ); |
1406 | return (unsigned)DiagObj->DiagArgumentsVal[Idx]; |
1407 | } |
1408 | |
1409 | /// Return the specified IdentifierInfo argument. |
1410 | /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo |
1411 | const IdentifierInfo *getArgIdentifier(unsigned Idx) const { |
1412 | assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo && |
1413 | "invalid argument accessor!" ); |
1414 | return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]); |
1415 | } |
1416 | |
1417 | /// Return the specified non-string argument in an opaque form. |
1418 | /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string |
1419 | intptr_t getRawArg(unsigned Idx) const { |
1420 | assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string && |
1421 | "invalid argument accessor!" ); |
1422 | return DiagObj->DiagArgumentsVal[Idx]; |
1423 | } |
1424 | |
1425 | /// Return the number of source ranges associated with this diagnostic. |
1426 | unsigned getNumRanges() const { |
1427 | return DiagObj->DiagRanges.size(); |
1428 | } |
1429 | |
1430 | /// \pre Idx < getNumRanges() |
1431 | const CharSourceRange &getRange(unsigned Idx) const { |
1432 | assert(Idx < getNumRanges() && "Invalid diagnostic range index!" ); |
1433 | return DiagObj->DiagRanges[Idx]; |
1434 | } |
1435 | |
1436 | /// Return an array reference for this diagnostic's ranges. |
1437 | ArrayRef<CharSourceRange> getRanges() const { |
1438 | return DiagObj->DiagRanges; |
1439 | } |
1440 | |
1441 | unsigned getNumFixItHints() const { |
1442 | return DiagObj->DiagFixItHints.size(); |
1443 | } |
1444 | |
1445 | const FixItHint &getFixItHint(unsigned Idx) const { |
1446 | assert(Idx < getNumFixItHints() && "Invalid index!" ); |
1447 | return DiagObj->DiagFixItHints[Idx]; |
1448 | } |
1449 | |
1450 | ArrayRef<FixItHint> getFixItHints() const { |
1451 | return DiagObj->DiagFixItHints; |
1452 | } |
1453 | |
1454 | /// Format this diagnostic into a string, substituting the |
1455 | /// formal arguments into the %0 slots. |
1456 | /// |
1457 | /// The result is appended onto the \p OutStr array. |
1458 | void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const; |
1459 | |
1460 | /// Format the given format-string into the output buffer using the |
1461 | /// arguments stored in this diagnostic. |
1462 | void FormatDiagnostic(const char *DiagStr, const char *DiagEnd, |
1463 | SmallVectorImpl<char> &OutStr) const; |
1464 | }; |
1465 | |
1466 | /** |
1467 | * Represents a diagnostic in a form that can be retained until its |
1468 | * corresponding source manager is destroyed. |
1469 | */ |
1470 | class StoredDiagnostic { |
1471 | unsigned ID; |
1472 | DiagnosticsEngine::Level Level; |
1473 | FullSourceLoc Loc; |
1474 | std::string Message; |
1475 | std::vector<CharSourceRange> Ranges; |
1476 | std::vector<FixItHint> FixIts; |
1477 | |
1478 | public: |
1479 | StoredDiagnostic() = default; |
1480 | StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info); |
1481 | StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID, |
1482 | StringRef Message); |
1483 | StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID, |
1484 | StringRef Message, FullSourceLoc Loc, |
1485 | ArrayRef<CharSourceRange> Ranges, |
1486 | ArrayRef<FixItHint> Fixits); |
1487 | |
1488 | /// Evaluates true when this object stores a diagnostic. |
1489 | explicit operator bool() const { return !Message.empty(); } |
1490 | |
1491 | unsigned getID() const { return ID; } |
1492 | DiagnosticsEngine::Level getLevel() const { return Level; } |
1493 | const FullSourceLoc &getLocation() const { return Loc; } |
1494 | StringRef getMessage() const { return Message; } |
1495 | |
1496 | void setLocation(FullSourceLoc Loc) { this->Loc = Loc; } |
1497 | |
1498 | using range_iterator = std::vector<CharSourceRange>::const_iterator; |
1499 | |
1500 | range_iterator range_begin() const { return Ranges.begin(); } |
1501 | range_iterator range_end() const { return Ranges.end(); } |
1502 | unsigned range_size() const { return Ranges.size(); } |
1503 | |
1504 | ArrayRef<CharSourceRange> getRanges() const { |
1505 | return llvm::makeArrayRef(Ranges); |
1506 | } |
1507 | |
1508 | using fixit_iterator = std::vector<FixItHint>::const_iterator; |
1509 | |
1510 | fixit_iterator fixit_begin() const { return FixIts.begin(); } |
1511 | fixit_iterator fixit_end() const { return FixIts.end(); } |
1512 | unsigned fixit_size() const { return FixIts.size(); } |
1513 | |
1514 | ArrayRef<FixItHint> getFixIts() const { |
1515 | return llvm::makeArrayRef(FixIts); |
1516 | } |
1517 | }; |
1518 | |
1519 | /// Abstract interface, implemented by clients of the front-end, which |
1520 | /// formats and prints fully processed diagnostics. |
1521 | class DiagnosticConsumer { |
1522 | protected: |
1523 | unsigned NumWarnings = 0; ///< Number of warnings reported |
1524 | unsigned NumErrors = 0; ///< Number of errors reported |
1525 | |
1526 | public: |
1527 | DiagnosticConsumer() = default; |
1528 | virtual ~DiagnosticConsumer(); |
1529 | |
1530 | unsigned getNumErrors() const { return NumErrors; } |
1531 | unsigned getNumWarnings() const { return NumWarnings; } |
1532 | virtual void clear() { NumWarnings = NumErrors = 0; } |
1533 | |
1534 | /// Callback to inform the diagnostic client that processing |
1535 | /// of a source file is beginning. |
1536 | /// |
1537 | /// Note that diagnostics may be emitted outside the processing of a source |
1538 | /// file, for example during the parsing of command line options. However, |
1539 | /// diagnostics with source range information are required to only be emitted |
1540 | /// in between BeginSourceFile() and EndSourceFile(). |
1541 | /// |
1542 | /// \param LangOpts The language options for the source file being processed. |
1543 | /// \param PP The preprocessor object being used for the source; this is |
1544 | /// optional, e.g., it may not be present when processing AST source files. |
1545 | virtual void BeginSourceFile(const LangOptions &LangOpts, |
1546 | const Preprocessor *PP = nullptr) {} |
1547 | |
1548 | /// Callback to inform the diagnostic client that processing |
1549 | /// of a source file has ended. |
1550 | /// |
1551 | /// The diagnostic client should assume that any objects made available via |
1552 | /// BeginSourceFile() are inaccessible. |
1553 | virtual void EndSourceFile() {} |
1554 | |
1555 | /// Callback to inform the diagnostic client that processing of all |
1556 | /// source files has ended. |
1557 | virtual void finish() {} |
1558 | |
1559 | /// Indicates whether the diagnostics handled by this |
1560 | /// DiagnosticConsumer should be included in the number of diagnostics |
1561 | /// reported by DiagnosticsEngine. |
1562 | /// |
1563 | /// The default implementation returns true. |
1564 | virtual bool IncludeInDiagnosticCounts() const; |
1565 | |
1566 | /// Handle this diagnostic, reporting it to the user or |
1567 | /// capturing it to a log as needed. |
1568 | /// |
1569 | /// The default implementation just keeps track of the total number of |
1570 | /// warnings and errors. |
1571 | virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, |
1572 | const Diagnostic &Info); |
1573 | }; |
1574 | |
1575 | /// A diagnostic client that ignores all diagnostics. |
1576 | class IgnoringDiagConsumer : public DiagnosticConsumer { |
1577 | virtual void anchor(); |
1578 | |
1579 | void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, |
1580 | const Diagnostic &Info) override { |
1581 | // Just ignore it. |
1582 | } |
1583 | }; |
1584 | |
1585 | /// Diagnostic consumer that forwards diagnostics along to an |
1586 | /// existing, already-initialized diagnostic consumer. |
1587 | /// |
1588 | class ForwardingDiagnosticConsumer : public DiagnosticConsumer { |
1589 | DiagnosticConsumer &Target; |
1590 | |
1591 | public: |
1592 | ForwardingDiagnosticConsumer(DiagnosticConsumer &Target) : Target(Target) {} |
1593 | ~ForwardingDiagnosticConsumer() override; |
1594 | |
1595 | void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, |
1596 | const Diagnostic &Info) override; |
1597 | void clear() override; |
1598 | |
1599 | bool IncludeInDiagnosticCounts() const override; |
1600 | }; |
1601 | |
1602 | // Struct used for sending info about how a type should be printed. |
1603 | struct TemplateDiffTypes { |
1604 | intptr_t FromType; |
1605 | intptr_t ToType; |
1606 | unsigned PrintTree : 1; |
1607 | unsigned PrintFromType : 1; |
1608 | unsigned ElideType : 1; |
1609 | unsigned ShowColors : 1; |
1610 | |
1611 | // The printer sets this variable to true if the template diff was used. |
1612 | unsigned TemplateDiffUsed : 1; |
1613 | }; |
1614 | |
1615 | /// Special character that the diagnostic printer will use to toggle the bold |
1616 | /// attribute. The character itself will be not be printed. |
1617 | const char ToggleHighlight = 127; |
1618 | |
1619 | /// ProcessWarningOptions - Initialize the diagnostic client and process the |
1620 | /// warning options specified on the command line. |
1621 | void ProcessWarningOptions(DiagnosticsEngine &Diags, |
1622 | const DiagnosticOptions &Opts, |
1623 | bool ReportDiags = true); |
1624 | |
1625 | } // namespace clang |
1626 | |
1627 | #endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H |
1628 | |