1 //===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the Diagnostic-related interfaces.
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_CLANG_DIAGNOSTIC_H
15 #define LLVM_CLANG_DIAGNOSTIC_H
17 #include "clang/Basic/DiagnosticIDs.h"
18 #include "clang/Basic/SourceLocation.h"
19 #include "llvm/ADT/ArrayRef.h"
20 #include "llvm/ADT/DenseMap.h"
21 #include "llvm/ADT/IntrusiveRefCntPtr.h"
22 #include "llvm/ADT/OwningPtr.h"
23 #include "llvm/Support/type_traits.h"
29 class DiagnosticConsumer;
30 class DiagnosticBuilder;
35 class DiagnosticErrorTrap;
36 class StoredDiagnostic;
38 /// \brief Annotates a diagnostic with some code that should be
39 /// inserted, removed, or replaced to fix the problem.
41 /// This kind of hint should be used when we are certain that the
42 /// introduction, removal, or modification of a particular (small!)
43 /// amount of code will correct a compilation error. The compiler
44 /// should also provide full recovery from such errors, such that
45 /// suppressing the diagnostic output can still result in successful
49 /// \brief Code that should be replaced to correct the error. Empty for an
51 CharSourceRange RemoveRange;
53 /// \brief The actual code to insert at the insertion location, as a
55 std::string CodeToInsert;
57 /// \brief Empty code modification hint, indicating that no code
58 /// modification is known.
59 FixItHint() : RemoveRange() { }
62 return !RemoveRange.isValid();
65 /// \brief Create a code modification hint that inserts the given
66 /// code string at a specific location.
67 static FixItHint CreateInsertion(SourceLocation InsertionLoc,
71 CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
72 Hint.CodeToInsert = Code;
76 /// \brief Create a code modification hint that removes the given
78 static FixItHint CreateRemoval(CharSourceRange RemoveRange) {
80 Hint.RemoveRange = RemoveRange;
83 static FixItHint CreateRemoval(SourceRange RemoveRange) {
84 return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange));
87 /// \brief Create a code modification hint that replaces the given
88 /// source range with the given code string.
89 static FixItHint CreateReplacement(CharSourceRange RemoveRange,
92 Hint.RemoveRange = RemoveRange;
93 Hint.CodeToInsert = Code;
97 static FixItHint CreateReplacement(SourceRange RemoveRange,
99 return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
103 /// DiagnosticsEngine - This concrete class is used by the front-end to report
104 /// problems and issues. It massages the diagnostics (e.g. handling things like
105 /// "report warnings as errors" and passes them off to the DiagnosticConsumer
106 /// for reporting to the user. DiagnosticsEngine is tied to one translation unit
107 /// and one SourceManager.
108 class DiagnosticsEngine : public llvm::RefCountedBase<DiagnosticsEngine> {
110 /// Level - The level of the diagnostic, after it has been through mapping.
112 Ignored = DiagnosticIDs::Ignored,
113 Note = DiagnosticIDs::Note,
114 Warning = DiagnosticIDs::Warning,
115 Error = DiagnosticIDs::Error,
116 Fatal = DiagnosticIDs::Fatal
119 /// ExtensionHandling - How do we handle otherwise-unmapped extension? This
120 /// is controlled by -pedantic and -pedantic-errors.
121 enum ExtensionHandling {
122 Ext_Ignore, Ext_Warn, Ext_Error
126 ak_std_string, // std::string
127 ak_c_string, // const char *
130 ak_identifierinfo, // IdentifierInfo
131 ak_qualtype, // QualType
132 ak_declarationname, // DeclarationName
133 ak_nameddecl, // NamedDecl *
134 ak_nestednamespec, // NestedNameSpecifier *
135 ak_declcontext // DeclContext *
138 /// Specifies which overload candidates to display when overload resolution
140 enum OverloadsShown {
141 Ovl_All, ///< Show all overloads.
142 Ovl_Best ///< Show just the "best" overload candidates.
145 /// ArgumentValue - This typedef represents on argument value, which is a
146 /// union discriminated by ArgumentKind, with a value.
147 typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
150 unsigned char AllExtensionsSilenced; // Used by __extension__
151 bool IgnoreAllWarnings; // Ignore all warnings: -w
152 bool WarningsAsErrors; // Treat warnings like errors.
153 bool EnableAllWarnings; // Enable all warnings.
154 bool ErrorsAsFatal; // Treat errors like fatal errors.
155 bool SuppressSystemWarnings; // Suppress warnings in system headers.
156 bool SuppressAllDiagnostics; // Suppress all diagnostics.
157 OverloadsShown ShowOverloads; // Which overload candidates to show.
158 unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit.
159 unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
161 ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
162 llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags;
163 DiagnosticConsumer *Client;
165 SourceManager *SourceMgr;
167 /// \brief Mapping information for diagnostics. Mapping info is
168 /// packed into four bits per diagnostic. The low three bits are the mapping
169 /// (an instance of diag::Mapping), or zero if unset. The high bit is set
170 /// when the mapping was established as a user mapping. If the high bit is
171 /// clear, then the low bits are set to the default value, and should be
172 /// mapped with -pedantic, -Werror, etc.
174 /// A new DiagState is created and kept around when diagnostic pragmas modify
175 /// the state so that we know what is the diagnostic state at any given
178 llvm::DenseMap<unsigned, DiagnosticMappingInfo> DiagMap;
181 typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::iterator
183 typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::const_iterator
186 void setMappingInfo(diag::kind Diag, DiagnosticMappingInfo Info) {
187 DiagMap[Diag] = Info;
190 DiagnosticMappingInfo &getOrAddMappingInfo(diag::kind Diag);
192 const_iterator begin() const { return DiagMap.begin(); }
193 const_iterator end() const { return DiagMap.end(); }
196 /// \brief Keeps and automatically disposes all DiagStates that we create.
197 std::list<DiagState> DiagStates;
199 /// \brief Represents a point in source where the diagnostic state was
200 /// modified because of a pragma. 'Loc' can be null if the point represents
201 /// the diagnostic state modifications done through the command-line.
202 struct DiagStatePoint {
205 DiagStatePoint(DiagState *State, FullSourceLoc Loc)
206 : State(State), Loc(Loc) { }
208 bool operator<(const DiagStatePoint &RHS) const {
209 // If Loc is invalid it means it came from <command-line>, in which case
210 // we regard it as coming before any valid source location.
211 if (RHS.Loc.isInvalid())
215 return Loc.isBeforeInTranslationUnitThan(RHS.Loc);
219 /// \brief A vector of all DiagStatePoints representing changes in diagnostic
220 /// state due to diagnostic pragmas. The vector is always sorted according to
221 /// the SourceLocation of the DiagStatePoint.
222 typedef std::vector<DiagStatePoint> DiagStatePointsTy;
223 mutable DiagStatePointsTy DiagStatePoints;
225 /// \brief Keeps the DiagState that was active during each diagnostic 'push'
226 /// so we can get back at it when we 'pop'.
227 std::vector<DiagState *> DiagStateOnPushStack;
229 DiagState *GetCurDiagState() const {
230 assert(!DiagStatePoints.empty());
231 return DiagStatePoints.back().State;
234 void PushDiagStatePoint(DiagState *State, SourceLocation L) {
235 FullSourceLoc Loc(L, *SourceMgr);
236 // Make sure that DiagStatePoints is always sorted according to Loc.
237 assert((Loc.isValid() || DiagStatePoints.empty()) &&
238 "Adding invalid loc point after another point");
239 assert((Loc.isInvalid() || DiagStatePoints.empty() ||
240 DiagStatePoints.back().Loc.isInvalid() ||
241 DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) &&
242 "Previous point loc comes after or is the same as new one");
243 DiagStatePoints.push_back(DiagStatePoint(State,
244 FullSourceLoc(Loc, *SourceMgr)));
247 /// \brief Finds the DiagStatePoint that contains the diagnostic state of
248 /// the given source location.
249 DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
251 /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
252 /// fatal error is emitted, and is sticky.
254 bool FatalErrorOccurred;
256 /// \brief Indicates that an unrecoverable error has occurred.
257 bool UnrecoverableErrorOccurred;
259 /// \brief Counts for DiagnosticErrorTrap to check whether an error occurred
260 /// during a parsing section, e.g. during parsing a function.
261 unsigned TrapNumErrorsOccurred;
262 unsigned TrapNumUnrecoverableErrorsOccurred;
264 /// LastDiagLevel - This is the level of the last diagnostic emitted. This is
265 /// used to emit continuation diagnostics with the same level as the
266 /// diagnostic that they follow.
267 DiagnosticIDs::Level LastDiagLevel;
269 unsigned NumWarnings; // Number of warnings reported
270 unsigned NumErrors; // Number of errors reported
271 unsigned NumErrorsSuppressed; // Number of errors suppressed
273 /// ArgToStringFn - A function pointer that converts an opaque diagnostic
274 /// argument to a strings. This takes the modifiers and argument that was
275 /// present in the diagnostic.
277 /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
278 /// arguments formatted for this diagnostic. Implementations of this function
279 /// can use this information to avoid redundancy across arguments.
281 /// This is a hack to avoid a layering violation between libbasic and libsema.
282 typedef void (*ArgToStringFnTy)(
283 ArgumentKind Kind, intptr_t Val,
284 const char *Modifier, unsigned ModifierLen,
285 const char *Argument, unsigned ArgumentLen,
286 const ArgumentValue *PrevArgs,
287 unsigned NumPrevArgs,
288 SmallVectorImpl<char> &Output,
290 SmallVectorImpl<intptr_t> &QualTypeVals);
291 void *ArgToStringCookie;
292 ArgToStringFnTy ArgToStringFn;
294 /// \brief ID of the "delayed" diagnostic, which is a (typically
295 /// fatal) diagnostic that had to be delayed because it was found
296 /// while emitting another diagnostic.
297 unsigned DelayedDiagID;
299 /// \brief First string argument for the delayed diagnostic.
300 std::string DelayedDiagArg1;
302 /// \brief Second string argument for the delayed diagnostic.
303 std::string DelayedDiagArg2;
306 explicit DiagnosticsEngine(
307 const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
308 DiagnosticConsumer *client = 0,
309 bool ShouldOwnClient = true);
310 ~DiagnosticsEngine();
312 const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
316 DiagnosticConsumer *getClient() { return Client; }
317 const DiagnosticConsumer *getClient() const { return Client; }
319 /// \brief Determine whether this \c DiagnosticsEngine object own its client.
320 bool ownsClient() const { return OwnsDiagClient; }
322 /// \brief Return the current diagnostic client along with ownership of that
324 DiagnosticConsumer *takeClient() {
325 OwnsDiagClient = false;
329 bool hasSourceManager() const { return SourceMgr != 0; }
330 SourceManager &getSourceManager() const {
331 assert(SourceMgr && "SourceManager not set!");
334 void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
336 //===--------------------------------------------------------------------===//
337 // DiagnosticsEngine characterization methods, used by a client to customize
338 // how diagnostics are emitted.
341 /// pushMappings - Copies the current DiagMappings and pushes the new copy
342 /// onto the top of the stack.
343 void pushMappings(SourceLocation Loc);
345 /// popMappings - Pops the current DiagMappings off the top of the stack
346 /// causing the new top of the stack to be the active mappings. Returns
347 /// true if the pop happens, false if there is only one DiagMapping on the
349 bool popMappings(SourceLocation Loc);
351 /// \brief Set the diagnostic client associated with this diagnostic object.
353 /// \param ShouldOwnClient true if the diagnostic object should take
354 /// ownership of \c client.
355 void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true);
357 /// setErrorLimit - Specify a limit for the number of errors we should
358 /// emit before giving up. Zero disables the limit.
359 void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }
361 /// \brief Specify the maximum number of template instantiation
362 /// notes to emit along with a given diagnostic.
363 void setTemplateBacktraceLimit(unsigned Limit) {
364 TemplateBacktraceLimit = Limit;
367 /// \brief Retrieve the maximum number of template instantiation
368 /// nodes to emit along with a given diagnostic.
369 unsigned getTemplateBacktraceLimit() const {
370 return TemplateBacktraceLimit;
373 /// setIgnoreAllWarnings - When set to true, any unmapped warnings are
374 /// ignored. If this and WarningsAsErrors are both set, then this one wins.
375 void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
376 bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
378 /// setEnableAllWarnings - When set to true, any unmapped ignored warnings
379 /// are no longer ignored. If this and IgnoreAllWarnings are both set,
380 /// then that one wins.
381 void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; }
382 bool getEnableAllWarnngs() const { return EnableAllWarnings; }
384 /// setWarningsAsErrors - When set to true, any warnings reported are issued
386 void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
387 bool getWarningsAsErrors() const { return WarningsAsErrors; }
389 /// setErrorsAsFatal - When set to true, any error reported is made a
391 void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
392 bool getErrorsAsFatal() const { return ErrorsAsFatal; }
394 /// setSuppressSystemWarnings - When set to true mask warnings that
395 /// come from system headers.
396 void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
397 bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
399 /// \brief Suppress all diagnostics, to silence the front end when we
400 /// know that we don't want any more diagnostics to be passed along to the
402 void setSuppressAllDiagnostics(bool Val = true) {
403 SuppressAllDiagnostics = Val;
405 bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
407 /// \brief Specify which overload candidates to show when overload resolution
408 /// fails. By default, we show all candidates.
409 void setShowOverloads(OverloadsShown Val) {
412 OverloadsShown getShowOverloads() const { return ShowOverloads; }
414 /// \brief Pretend that the last diagnostic issued was ignored. This can
415 /// be used by clients who suppress diagnostics themselves.
416 void setLastDiagnosticIgnored() {
417 LastDiagLevel = DiagnosticIDs::Ignored;
420 /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
421 /// extension diagnostics are mapped onto ignore/warning/error. This
422 /// corresponds to the GCC -pedantic and -pedantic-errors option.
423 void setExtensionHandlingBehavior(ExtensionHandling H) {
426 ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; }
428 /// AllExtensionsSilenced - This is a counter bumped when an __extension__
429 /// block is encountered. When non-zero, all extension diagnostics are
430 /// entirely silenced, no matter how they are mapped.
431 void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
432 void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
433 bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
435 /// \brief This allows the client to specify that certain
436 /// warnings are ignored. Notes can never be mapped, errors can only be
437 /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
439 /// \param Loc The source location that this change of diagnostic state should
440 /// take affect. It can be null if we are setting the latest state.
441 void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
444 /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
445 /// "unknown-pragmas" to have the specified mapping. This returns true and
446 /// ignores the request if "Group" was unknown, false otherwise.
448 /// 'Loc' is the source location that this change of diagnostic state should
449 /// take affect. It can be null if we are setting the state from command-line.
450 bool setDiagnosticGroupMapping(StringRef Group, diag::Mapping Map,
451 SourceLocation Loc = SourceLocation());
453 /// \brief Set the warning-as-error flag for the given diagnostic group. This
454 /// function always only operates on the current diagnostic state.
456 /// \returns True if the given group is unknown, false otherwise.
457 bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled);
459 /// \brief Set the error-as-fatal flag for the given diagnostic group. This
460 /// function always only operates on the current diagnostic state.
462 /// \returns True if the given group is unknown, false otherwise.
463 bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);
465 bool hasErrorOccurred() const { return ErrorOccurred; }
466 bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
468 /// \brief Determine whether any kind of unrecoverable error has occurred.
469 bool hasUnrecoverableErrorOccurred() const {
470 return FatalErrorOccurred || UnrecoverableErrorOccurred;
473 unsigned getNumWarnings() const { return NumWarnings; }
475 void setNumWarnings(unsigned NumWarnings) {
476 this->NumWarnings = NumWarnings;
479 /// getCustomDiagID - Return an ID for a diagnostic with the specified message
480 /// and level. If this is the first request for this diagnosic, it is
481 /// registered and created, otherwise the existing ID is returned.
482 unsigned getCustomDiagID(Level L, StringRef Message) {
483 return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
486 /// ConvertArgToString - This method converts a diagnostic argument (as an
487 /// intptr_t) into the string that represents it.
488 void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
489 const char *Modifier, unsigned ModLen,
490 const char *Argument, unsigned ArgLen,
491 const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
492 SmallVectorImpl<char> &Output,
493 SmallVectorImpl<intptr_t> &QualTypeVals) const {
494 ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
495 PrevArgs, NumPrevArgs, Output, ArgToStringCookie,
499 void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
501 ArgToStringCookie = Cookie;
504 /// \brief Reset the state of the diagnostic object to its initial
508 //===--------------------------------------------------------------------===//
509 // DiagnosticsEngine classification and reporting interfaces.
512 /// \brief Based on the way the client configured the DiagnosticsEngine
513 /// object, classify the specified diagnostic ID into a Level, consumable by
514 /// the DiagnosticConsumer.
516 /// \param Loc The source location we are interested in finding out the
517 /// diagnostic state. Can be null in order to query the latest state.
518 Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
519 return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
522 /// Report - Issue the message to the client. @c DiagID is a member of the
523 /// @c diag::kind enum. This actually returns aninstance of DiagnosticBuilder
524 /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed.
525 /// @c Pos represents the source location associated with the diagnostic,
526 /// which can be an invalid location if no position information is available.
527 inline DiagnosticBuilder Report(SourceLocation Pos, unsigned DiagID);
528 inline DiagnosticBuilder Report(unsigned DiagID);
530 void Report(const StoredDiagnostic &storedDiag);
532 /// \brief Determine whethere there is already a diagnostic in flight.
533 bool isDiagnosticInFlight() const { return CurDiagID != ~0U; }
535 /// \brief Set the "delayed" diagnostic that will be emitted once
536 /// the current diagnostic completes.
538 /// If a diagnostic is already in-flight but the front end must
539 /// report a problem (e.g., with an inconsistent file system
540 /// state), this routine sets a "delayed" diagnostic that will be
541 /// emitted after the current diagnostic completes. This should
542 /// only be used for fatal errors detected at inconvenient
543 /// times. If emitting a delayed diagnostic causes a second delayed
544 /// diagnostic to be introduced, that second delayed diagnostic
547 /// \param DiagID The ID of the diagnostic being delayed.
549 /// \param Arg1 A string argument that will be provided to the
550 /// diagnostic. A copy of this string will be stored in the
551 /// DiagnosticsEngine object itself.
553 /// \param Arg2 A string argument that will be provided to the
554 /// diagnostic. A copy of this string will be stored in the
555 /// DiagnosticsEngine object itself.
556 void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
557 StringRef Arg2 = "");
559 /// \brief Clear out the current diagnostic.
560 void Clear() { CurDiagID = ~0U; }
563 /// \brief Report the delayed diagnostic.
564 void ReportDelayed();
566 // This is private state used by DiagnosticBuilder. We put it here instead of
567 // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
568 // object. This implementation choice means that we can only have one
569 // diagnostic "in flight" at a time, but this seems to be a reasonable
570 // tradeoff to keep these objects small. Assertions verify that only one
571 // diagnostic is in flight at a time.
572 friend class DiagnosticIDs;
573 friend class DiagnosticBuilder;
574 friend class Diagnostic;
575 friend class PartialDiagnostic;
576 friend class DiagnosticErrorTrap;
578 /// CurDiagLoc - This is the location of the current diagnostic that is in
580 SourceLocation CurDiagLoc;
582 /// CurDiagID - This is the ID of the current diagnostic that is in flight.
583 /// This is set to ~0U when there is no diagnostic in flight.
587 /// MaxArguments - The maximum number of arguments we can hold. We currently
588 /// only support up to 10 arguments (%0-%9). A single diagnostic with more
589 /// than that almost certainly has to be simplified anyway.
593 /// NumDiagArgs - This contains the number of entries in Arguments.
594 signed char NumDiagArgs;
595 /// NumRanges - This is the number of ranges in the DiagRanges array.
596 unsigned char NumDiagRanges;
597 /// \brief The number of code modifications hints in the
598 /// FixItHints array.
599 unsigned char NumFixItHints;
601 /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
602 /// values, with one for each argument. This specifies whether the argument
603 /// is in DiagArgumentsStr or in DiagArguments.
604 unsigned char DiagArgumentsKind[MaxArguments];
606 /// DiagArgumentsStr - This holds the values of each string argument for the
607 /// current diagnostic. This value is only used when the corresponding
608 /// ArgumentKind is ak_std_string.
609 std::string DiagArgumentsStr[MaxArguments];
611 /// DiagArgumentsVal - The values for the various substitution positions. This
612 /// is used when the argument is not an std::string. The specific value is
613 /// mangled into an intptr_t and the interpretation depends on exactly what
614 /// sort of argument kind it is.
615 intptr_t DiagArgumentsVal[MaxArguments];
617 /// DiagRanges - The list of ranges added to this diagnostic. It currently
618 /// only support 10 ranges, could easily be extended if needed.
619 CharSourceRange DiagRanges[10];
621 enum { MaxFixItHints = 6 };
623 /// FixItHints - If valid, provides a hint with some code
624 /// to insert, remove, or modify at a particular position.
625 FixItHint FixItHints[MaxFixItHints];
627 /// ProcessDiag - This is the method used to report a diagnostic that is
628 /// finally fully formed.
630 /// \returns true if the diagnostic was emitted, false if it was
633 return Diags->ProcessDiag(*this);
636 friend class ASTReader;
637 friend class ASTWriter;
640 /// \brief RAII class that determines when any errors have occurred
641 /// between the time the instance was created and the time it was
643 class DiagnosticErrorTrap {
644 DiagnosticsEngine &Diag;
646 unsigned NumUnrecoverableErrors;
649 explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag)
650 : Diag(Diag) { reset(); }
652 /// \brief Determine whether any errors have occurred since this
653 /// object instance was created.
654 bool hasErrorOccurred() const {
655 return Diag.TrapNumErrorsOccurred > NumErrors;
658 /// \brief Determine whether any unrecoverable errors have occurred since this
659 /// object instance was created.
660 bool hasUnrecoverableErrorOccurred() const {
661 return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
664 // Set to initial state of "no errors occurred".
666 NumErrors = Diag.TrapNumErrorsOccurred;
667 NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
671 //===----------------------------------------------------------------------===//
673 //===----------------------------------------------------------------------===//
675 /// DiagnosticBuilder - This is a little helper class used to produce
676 /// diagnostics. This is constructed by the DiagnosticsEngine::Report method,
677 /// and allows insertion of extra information (arguments and source ranges) into
678 /// the currently "in flight" diagnostic. When the temporary for the builder is
679 /// destroyed, the diagnostic is issued.
681 /// Note that many of these will be created as temporary objects (many call
682 /// sites), so we want them to be small and we never want their address taken.
683 /// This ensures that compilers with somewhat reasonable optimizers will promote
684 /// the common fields to registers, eliminating increments of the NumArgs field,
686 class DiagnosticBuilder {
687 mutable DiagnosticsEngine *DiagObj;
688 mutable unsigned NumArgs, NumRanges, NumFixItHints;
690 void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
691 friend class DiagnosticsEngine;
692 explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
693 : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {}
695 friend class PartialDiagnostic;
701 /// Copy constructor. When copied, this "takes" the diagnostic info from the
702 /// input and neuters it.
703 DiagnosticBuilder(const DiagnosticBuilder &D) {
707 NumRanges = D.NumRanges;
708 NumFixItHints = D.NumFixItHints;
711 /// \brief Simple enumeration value used to give a name to the
712 /// suppress-diagnostic constructor.
713 enum SuppressKind { Suppress };
715 /// \brief Create an empty DiagnosticBuilder object that represents
716 /// no actual diagnostic.
717 explicit DiagnosticBuilder(SuppressKind)
718 : DiagObj(0), NumArgs(0), NumRanges(0), NumFixItHints(0) { }
720 /// \brief Force the diagnostic builder to emit the diagnostic now.
722 /// Once this function has been called, the DiagnosticBuilder object
723 /// should not be used again before it is destroyed.
725 /// \returns true if a diagnostic was emitted, false if the
726 /// diagnostic was suppressed.
729 /// Destructor - The dtor emits the diagnostic if it hasn't already
731 ~DiagnosticBuilder() { Emit(); }
733 /// isActive - Determine whether this diagnostic is still active.
734 bool isActive() const { return DiagObj != 0; }
736 /// \brief Retrieve the active diagnostic ID.
738 /// \pre \c isActive()
739 unsigned getDiagID() const {
740 assert(isActive() && "DiagnosticsEngine is inactive");
741 return DiagObj->CurDiagID;
744 /// \brief Clear out the current diagnostic.
745 void Clear() { DiagObj = 0; }
747 /// Operator bool: conversion of DiagnosticBuilder to bool always returns
748 /// true. This allows is to be used in boolean error contexts like:
749 /// return Diag(...);
750 operator bool() const { return true; }
752 void AddString(StringRef S) const {
753 assert(NumArgs < DiagnosticsEngine::MaxArguments &&
754 "Too many arguments to diagnostic!");
756 DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string;
757 DiagObj->DiagArgumentsStr[NumArgs++] = S;
761 void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
762 assert(NumArgs < DiagnosticsEngine::MaxArguments &&
763 "Too many arguments to diagnostic!");
765 DiagObj->DiagArgumentsKind[NumArgs] = Kind;
766 DiagObj->DiagArgumentsVal[NumArgs++] = V;
770 void AddSourceRange(const CharSourceRange &R) const {
772 sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
773 "Too many arguments to diagnostic!");
775 DiagObj->DiagRanges[NumRanges++] = R;
778 void AddFixItHint(const FixItHint &Hint) const {
779 assert(NumFixItHints < DiagnosticsEngine::MaxFixItHints &&
780 "Too many fix-it hints!");
781 if (NumFixItHints >= DiagnosticsEngine::MaxFixItHints)
782 return; // Don't crash in release builds
784 DiagObj->FixItHints[NumFixItHints++] = Hint;
788 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
794 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
796 DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
797 DiagnosticsEngine::ak_c_string);
801 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
802 DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
806 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
807 DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
811 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
813 DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
817 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
818 const IdentifierInfo *II) {
819 DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
820 DiagnosticsEngine::ak_identifierinfo);
824 // Adds a DeclContext to the diagnostic. The enable_if template magic is here
825 // so that we only match those arguments that are (statically) DeclContexts;
826 // other arguments that derive from DeclContext (e.g., RecordDecls) will not
830 typename llvm::enable_if<llvm::is_same<T, DeclContext>,
831 const DiagnosticBuilder &>::type
832 operator<<(const DiagnosticBuilder &DB, T *DC) {
833 DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
834 DiagnosticsEngine::ak_declcontext);
838 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
839 const SourceRange &R) {
840 DB.AddSourceRange(CharSourceRange::getTokenRange(R));
844 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
845 const CharSourceRange &R) {
846 DB.AddSourceRange(R);
850 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
851 const FixItHint &Hint) {
852 DB.AddFixItHint(Hint);
856 /// Report - Issue the message to the client. DiagID is a member of the
857 /// diag::kind enum. This actually returns a new instance of DiagnosticBuilder
858 /// which emits the diagnostics (through ProcessDiag) when it is destroyed.
859 inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
861 assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
864 return DiagnosticBuilder(this);
866 inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
867 return Report(SourceLocation(), DiagID);
870 //===----------------------------------------------------------------------===//
872 //===----------------------------------------------------------------------===//
874 /// Diagnostic - This is a little helper class (which is basically a smart
875 /// pointer that forward info from DiagnosticsEngine) that allows clients to
876 /// enquire about the currently in-flight diagnostic.
878 const DiagnosticsEngine *DiagObj;
879 StringRef StoredDiagMessage;
881 explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {}
882 Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage)
883 : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
885 const DiagnosticsEngine *getDiags() const { return DiagObj; }
886 unsigned getID() const { return DiagObj->CurDiagID; }
887 const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
888 bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
889 SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}
891 unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
893 /// getArgKind - Return the kind of the specified index. Based on the kind
894 /// of argument, the accessors below can be used to get the value.
895 DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const {
896 assert(Idx < getNumArgs() && "Argument index out of range!");
897 return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
900 /// getArgStdStr - Return the provided argument string specified by Idx.
901 const std::string &getArgStdStr(unsigned Idx) const {
902 assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
903 "invalid argument accessor!");
904 return DiagObj->DiagArgumentsStr[Idx];
907 /// getArgCStr - Return the specified C string argument.
908 const char *getArgCStr(unsigned Idx) const {
909 assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
910 "invalid argument accessor!");
911 return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
914 /// getArgSInt - Return the specified signed integer argument.
915 int getArgSInt(unsigned Idx) const {
916 assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
917 "invalid argument accessor!");
918 return (int)DiagObj->DiagArgumentsVal[Idx];
921 /// getArgUInt - Return the specified unsigned integer argument.
922 unsigned getArgUInt(unsigned Idx) const {
923 assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
924 "invalid argument accessor!");
925 return (unsigned)DiagObj->DiagArgumentsVal[Idx];
928 /// getArgIdentifier - Return the specified IdentifierInfo argument.
929 const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
930 assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
931 "invalid argument accessor!");
932 return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
935 /// getRawArg - Return the specified non-string argument in an opaque form.
936 intptr_t getRawArg(unsigned Idx) const {
937 assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
938 "invalid argument accessor!");
939 return DiagObj->DiagArgumentsVal[Idx];
943 /// getNumRanges - Return the number of source ranges associated with this
945 unsigned getNumRanges() const {
946 return DiagObj->NumDiagRanges;
949 const CharSourceRange &getRange(unsigned Idx) const {
950 assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
951 return DiagObj->DiagRanges[Idx];
954 unsigned getNumFixItHints() const {
955 return DiagObj->NumFixItHints;
958 const FixItHint &getFixItHint(unsigned Idx) const {
959 return DiagObj->FixItHints[Idx];
962 const FixItHint *getFixItHints() const {
963 return DiagObj->NumFixItHints?
964 &DiagObj->FixItHints[0] : 0;
967 /// FormatDiagnostic - Format this diagnostic into a string, substituting the
968 /// formal arguments into the %0 slots. The result is appended onto the Str
970 void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;
972 /// FormatDiagnostic - Format the given format-string into the
973 /// output buffer using the arguments stored in this diagnostic.
974 void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
975 SmallVectorImpl<char> &OutStr) const;
979 * \brief Represents a diagnostic in a form that can be retained until its
980 * corresponding source manager is destroyed.
982 class StoredDiagnostic {
984 DiagnosticsEngine::Level Level;
987 std::vector<CharSourceRange> Ranges;
988 std::vector<FixItHint> FixIts;
992 StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
993 StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
995 StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
996 StringRef Message, FullSourceLoc Loc,
997 ArrayRef<CharSourceRange> Ranges,
998 ArrayRef<FixItHint> Fixits);
1001 /// \brief Evaluates true when this object stores a diagnostic.
1002 operator bool() const { return Message.size() > 0; }
1004 unsigned getID() const { return ID; }
1005 DiagnosticsEngine::Level getLevel() const { return Level; }
1006 const FullSourceLoc &getLocation() const { return Loc; }
1007 StringRef getMessage() const { return Message; }
1009 void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
1011 typedef std::vector<CharSourceRange>::const_iterator range_iterator;
1012 range_iterator range_begin() const { return Ranges.begin(); }
1013 range_iterator range_end() const { return Ranges.end(); }
1014 unsigned range_size() const { return Ranges.size(); }
1016 typedef std::vector<FixItHint>::const_iterator fixit_iterator;
1017 fixit_iterator fixit_begin() const { return FixIts.begin(); }
1018 fixit_iterator fixit_end() const { return FixIts.end(); }
1019 unsigned fixit_size() const { return FixIts.size(); }
1022 /// DiagnosticConsumer - This is an abstract interface implemented by clients of
1023 /// the front-end, which formats and prints fully processed diagnostics.
1024 class DiagnosticConsumer {
1026 unsigned NumWarnings; // Number of warnings reported
1027 unsigned NumErrors; // Number of errors reported
1030 DiagnosticConsumer() : NumWarnings(0), NumErrors(0) { }
1032 unsigned getNumErrors() const { return NumErrors; }
1033 unsigned getNumWarnings() const { return NumWarnings; }
1035 virtual ~DiagnosticConsumer();
1037 /// BeginSourceFile - Callback to inform the diagnostic client that processing
1038 /// of a source file is beginning.
1040 /// Note that diagnostics may be emitted outside the processing of a source
1041 /// file, for example during the parsing of command line options. However,
1042 /// diagnostics with source range information are required to only be emitted
1043 /// in between BeginSourceFile() and EndSourceFile().
1045 /// \arg LO - The language options for the source file being processed.
1046 /// \arg PP - The preprocessor object being used for the source; this optional
1047 /// and may not be present, for example when processing AST source files.
1048 virtual void BeginSourceFile(const LangOptions &LangOpts,
1049 const Preprocessor *PP = 0) {}
1051 /// EndSourceFile - Callback to inform the diagnostic client that processing
1052 /// of a source file has ended. The diagnostic client should assume that any
1053 /// objects made available via \see BeginSourceFile() are inaccessible.
1054 virtual void EndSourceFile() {}
1056 /// IncludeInDiagnosticCounts - This method (whose default implementation
1057 /// returns true) indicates whether the diagnostics handled by this
1058 /// DiagnosticConsumer should be included in the number of diagnostics
1059 /// reported by DiagnosticsEngine.
1060 virtual bool IncludeInDiagnosticCounts() const;
1062 /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
1063 /// capturing it to a log as needed.
1065 /// Default implementation just keeps track of the total number of warnings
1067 virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1068 const Diagnostic &Info);
1070 /// \brief Clone the diagnostic consumer, producing an equivalent consumer
1071 /// that can be used in a different context.
1072 virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const = 0;
1075 /// IgnoringDiagConsumer - This is a diagnostic client that just ignores all
1077 class IgnoringDiagConsumer : public DiagnosticConsumer {
1078 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1079 const Diagnostic &Info) {
1082 DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
1083 return new IgnoringDiagConsumer();
1087 } // end namespace clang