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