• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief Defines the Diagnostic-related interfaces.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_DIAGNOSTIC_H
16 #define LLVM_CLANG_DIAGNOSTIC_H
17 
18 #include "clang/Basic/DiagnosticIDs.h"
19 #include "clang/Basic/SourceLocation.h"
20 #include "llvm/ADT/ArrayRef.h"
21 #include "llvm/ADT/DenseMap.h"
22 #include "llvm/ADT/IntrusiveRefCntPtr.h"
23 #include "llvm/ADT/OwningPtr.h"
24 #include "llvm/Support/type_traits.h"
25 
26 #include <vector>
27 #include <list>
28 
29 namespace clang {
30   class DiagnosticConsumer;
31   class DiagnosticBuilder;
32   class IdentifierInfo;
33   class DeclContext;
34   class LangOptions;
35   class Preprocessor;
36   class DiagnosticErrorTrap;
37   class StoredDiagnostic;
38 
39 /// \brief Annotates a diagnostic with some code that should be
40 /// inserted, removed, or replaced to fix the problem.
41 ///
42 /// This kind of hint should be used when we are certain that the
43 /// introduction, removal, or modification of a particular (small!)
44 /// amount of code will correct a compilation error. The compiler
45 /// should also provide full recovery from such errors, such that
46 /// suppressing the diagnostic output can still result in successful
47 /// compilation.
48 class FixItHint {
49 public:
50   /// \brief Code that should be replaced to correct the error. Empty for an
51   /// insertion hint.
52   CharSourceRange RemoveRange;
53 
54   /// \brief Code in the specific range that should be inserted in the insertion
55   /// location.
56   CharSourceRange InsertFromRange;
57 
58   /// \brief The actual code to insert at the insertion location, as a
59   /// string.
60   std::string CodeToInsert;
61 
62   bool BeforePreviousInsertions;
63 
64   /// \brief Empty code modification hint, indicating that no code
65   /// modification is known.
FixItHint()66   FixItHint() : BeforePreviousInsertions(false) { }
67 
isNull()68   bool isNull() const {
69     return !RemoveRange.isValid();
70   }
71 
72   /// \brief Create a code modification hint that inserts the given
73   /// code string at a specific location.
74   static FixItHint CreateInsertion(SourceLocation InsertionLoc,
75                                    StringRef Code,
76                                    bool BeforePreviousInsertions = false) {
77     FixItHint Hint;
78     Hint.RemoveRange =
79       CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
80     Hint.CodeToInsert = Code;
81     Hint.BeforePreviousInsertions = BeforePreviousInsertions;
82     return Hint;
83   }
84 
85   /// \brief Create a code modification hint that inserts the given
86   /// code from \p FromRange at a specific location.
87   static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc,
88                                             CharSourceRange FromRange,
89                                         bool BeforePreviousInsertions = false) {
90     FixItHint Hint;
91     Hint.RemoveRange =
92       CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
93     Hint.InsertFromRange = FromRange;
94     Hint.BeforePreviousInsertions = BeforePreviousInsertions;
95     return Hint;
96   }
97 
98   /// \brief Create a code modification hint that removes the given
99   /// source range.
CreateRemoval(CharSourceRange RemoveRange)100   static FixItHint CreateRemoval(CharSourceRange RemoveRange) {
101     FixItHint Hint;
102     Hint.RemoveRange = RemoveRange;
103     return Hint;
104   }
CreateRemoval(SourceRange RemoveRange)105   static FixItHint CreateRemoval(SourceRange RemoveRange) {
106     return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange));
107   }
108 
109   /// \brief Create a code modification hint that replaces the given
110   /// source range with the given code string.
CreateReplacement(CharSourceRange RemoveRange,StringRef Code)111   static FixItHint CreateReplacement(CharSourceRange RemoveRange,
112                                      StringRef Code) {
113     FixItHint Hint;
114     Hint.RemoveRange = RemoveRange;
115     Hint.CodeToInsert = Code;
116     return Hint;
117   }
118 
CreateReplacement(SourceRange RemoveRange,StringRef Code)119   static FixItHint CreateReplacement(SourceRange RemoveRange,
120                                      StringRef Code) {
121     return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
122   }
123 };
124 
125 /// \brief Concrete class used by the front-end to report problems and issues.
126 ///
127 /// This massages the diagnostics (e.g. handling things like "report warnings
128 /// as errors" and passes them off to the DiagnosticConsumer for reporting to
129 /// the user. DiagnosticsEngine is tied to one translation unit and one
130 /// SourceManager.
131 class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
132 public:
133   /// \brief The level of the diagnostic, after it has been through mapping.
134   enum Level {
135     Ignored = DiagnosticIDs::Ignored,
136     Note = DiagnosticIDs::Note,
137     Warning = DiagnosticIDs::Warning,
138     Error = DiagnosticIDs::Error,
139     Fatal = DiagnosticIDs::Fatal
140   };
141 
142   /// \brief How do we handle otherwise-unmapped extension?
143   ///
144   /// This is controlled by -pedantic and -pedantic-errors.
145   enum ExtensionHandling {
146     Ext_Ignore, Ext_Warn, Ext_Error
147   };
148 
149   enum ArgumentKind {
150     ak_std_string,      ///< std::string
151     ak_c_string,        ///< const char *
152     ak_sint,            ///< int
153     ak_uint,            ///< unsigned
154     ak_identifierinfo,  ///< IdentifierInfo
155     ak_qualtype,        ///< QualType
156     ak_declarationname, ///< DeclarationName
157     ak_nameddecl,       ///< NamedDecl *
158     ak_nestednamespec,  ///< NestedNameSpecifier *
159     ak_declcontext,     ///< DeclContext *
160     ak_qualtype_pair    ///< pair<QualType, QualType>
161   };
162 
163   /// \brief Specifies which overload candidates to display when overload
164   /// resolution fails.
165   enum OverloadsShown {
166     Ovl_All,  ///< Show all overloads.
167     Ovl_Best  ///< Show just the "best" overload candidates.
168   };
169 
170   /// \brief Represents on argument value, which is a union discriminated
171   /// by ArgumentKind, with a value.
172   typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
173 
174 private:
175   unsigned char AllExtensionsSilenced; // Used by __extension__
176   bool IgnoreAllWarnings;        // Ignore all warnings: -w
177   bool WarningsAsErrors;         // Treat warnings like errors.
178   bool EnableAllWarnings;        // Enable all warnings.
179   bool ErrorsAsFatal;            // Treat errors like fatal errors.
180   bool SuppressSystemWarnings;   // Suppress warnings in system headers.
181   bool SuppressAllDiagnostics;   // Suppress all diagnostics.
182   bool ElideType;                // Elide common types of templates.
183   bool PrintTemplateTree;        // Print a tree when comparing templates.
184   bool ShowColors;               // Color printing is enabled.
185   OverloadsShown ShowOverloads;  // Which overload candidates to show.
186   unsigned ErrorLimit;           // Cap of # errors emitted, 0 -> no limit.
187   unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
188                                    // 0 -> no limit.
189   unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation
190                                     // backtrace stack, 0 -> no limit.
191   ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
192   IntrusiveRefCntPtr<DiagnosticIDs> Diags;
193   DiagnosticConsumer *Client;
194   bool OwnsDiagClient;
195   SourceManager *SourceMgr;
196 
197   /// \brief Mapping information for diagnostics.
198   ///
199   /// Mapping info is packed into four bits per diagnostic.  The low three
200   /// bits are the mapping (an instance of diag::Mapping), or zero if unset.
201   /// The high bit is set when the mapping was established as a user mapping.
202   /// If the high bit is clear, then the low bits are set to the default
203   /// value, and should be mapped with -pedantic, -Werror, etc.
204   ///
205   /// A new DiagState is created and kept around when diagnostic pragmas modify
206   /// the state so that we know what is the diagnostic state at any given
207   /// source location.
208   class DiagState {
209     llvm::DenseMap<unsigned, DiagnosticMappingInfo> DiagMap;
210 
211   public:
212     typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::iterator
213       iterator;
214     typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::const_iterator
215       const_iterator;
216 
setMappingInfo(diag::kind Diag,DiagnosticMappingInfo Info)217     void setMappingInfo(diag::kind Diag, DiagnosticMappingInfo Info) {
218       DiagMap[Diag] = Info;
219     }
220 
221     DiagnosticMappingInfo &getOrAddMappingInfo(diag::kind Diag);
222 
begin()223     const_iterator begin() const { return DiagMap.begin(); }
end()224     const_iterator end() const { return DiagMap.end(); }
225   };
226 
227   /// \brief Keeps and automatically disposes all DiagStates that we create.
228   std::list<DiagState> DiagStates;
229 
230   /// \brief Represents a point in source where the diagnostic state was
231   /// modified because of a pragma.
232   ///
233   /// 'Loc' can be null if the point represents the diagnostic state
234   /// modifications done through the command-line.
235   struct DiagStatePoint {
236     DiagState *State;
237     FullSourceLoc Loc;
DiagStatePointDiagStatePoint238     DiagStatePoint(DiagState *State, FullSourceLoc Loc)
239       : State(State), Loc(Loc) { }
240 
241     bool operator<(const DiagStatePoint &RHS) const {
242       // If Loc is invalid it means it came from <command-line>, in which case
243       // we regard it as coming before any valid source location.
244       if (RHS.Loc.isInvalid())
245         return false;
246       if (Loc.isInvalid())
247         return true;
248       return Loc.isBeforeInTranslationUnitThan(RHS.Loc);
249     }
250   };
251 
252   /// \brief A sorted vector of all DiagStatePoints representing changes in
253   /// diagnostic state due to diagnostic pragmas.
254   ///
255   /// The vector is always sorted according to the SourceLocation of the
256   /// DiagStatePoint.
257   typedef std::vector<DiagStatePoint> DiagStatePointsTy;
258   mutable DiagStatePointsTy DiagStatePoints;
259 
260   /// \brief Keeps the DiagState that was active during each diagnostic 'push'
261   /// so we can get back at it when we 'pop'.
262   std::vector<DiagState *> DiagStateOnPushStack;
263 
GetCurDiagState()264   DiagState *GetCurDiagState() const {
265     assert(!DiagStatePoints.empty());
266     return DiagStatePoints.back().State;
267   }
268 
PushDiagStatePoint(DiagState * State,SourceLocation L)269   void PushDiagStatePoint(DiagState *State, SourceLocation L) {
270     FullSourceLoc Loc(L, getSourceManager());
271     // Make sure that DiagStatePoints is always sorted according to Loc.
272     assert(Loc.isValid() && "Adding invalid loc point");
273     assert(!DiagStatePoints.empty() &&
274            (DiagStatePoints.back().Loc.isInvalid() ||
275             DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) &&
276            "Previous point loc comes after or is the same as new one");
277     DiagStatePoints.push_back(DiagStatePoint(State, Loc));
278   }
279 
280   /// \brief Finds the DiagStatePoint that contains the diagnostic state of
281   /// the given source location.
282   DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
283 
284   /// \brief Sticky flag set to \c true when an error is emitted.
285   bool ErrorOccurred;
286 
287   /// \brief Sticky flag set to \c true when a fatal error is emitted.
288   bool FatalErrorOccurred;
289 
290   /// \brief Indicates that an unrecoverable error has occurred.
291   bool UnrecoverableErrorOccurred;
292 
293   /// \brief Counts for DiagnosticErrorTrap to check whether an error occurred
294   /// during a parsing section, e.g. during parsing a function.
295   unsigned TrapNumErrorsOccurred;
296   unsigned TrapNumUnrecoverableErrorsOccurred;
297 
298   /// \brief The level of the last diagnostic emitted.
299   ///
300   /// This is used to emit continuation diagnostics with the same level as the
301   /// diagnostic that they follow.
302   DiagnosticIDs::Level LastDiagLevel;
303 
304   unsigned NumWarnings;         ///< Number of warnings reported
305   unsigned NumErrors;           ///< Number of errors reported
306   unsigned NumErrorsSuppressed; ///< Number of errors suppressed
307 
308   /// \brief A function pointer that converts an opaque diagnostic
309   /// argument to a strings.
310   ///
311   /// This takes the modifiers and argument that was present in the diagnostic.
312   ///
313   /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
314   /// arguments formatted for this diagnostic.  Implementations of this function
315   /// can use this information to avoid redundancy across arguments.
316   ///
317   /// This is a hack to avoid a layering violation between libbasic and libsema.
318   typedef void (*ArgToStringFnTy)(
319       ArgumentKind Kind, intptr_t Val,
320       const char *Modifier, unsigned ModifierLen,
321       const char *Argument, unsigned ArgumentLen,
322       const ArgumentValue *PrevArgs,
323       unsigned NumPrevArgs,
324       SmallVectorImpl<char> &Output,
325       void *Cookie,
326       ArrayRef<intptr_t> QualTypeVals);
327   void *ArgToStringCookie;
328   ArgToStringFnTy ArgToStringFn;
329 
330   /// \brief ID of the "delayed" diagnostic, which is a (typically
331   /// fatal) diagnostic that had to be delayed because it was found
332   /// while emitting another diagnostic.
333   unsigned DelayedDiagID;
334 
335   /// \brief First string argument for the delayed diagnostic.
336   std::string DelayedDiagArg1;
337 
338   /// \brief Second string argument for the delayed diagnostic.
339   std::string DelayedDiagArg2;
340 
341 public:
342   explicit DiagnosticsEngine(
343                       const IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
344                       DiagnosticConsumer *client = 0,
345                       bool ShouldOwnClient = true);
346   ~DiagnosticsEngine();
347 
getDiagnosticIDs()348   const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
349     return Diags;
350   }
351 
getClient()352   DiagnosticConsumer *getClient() { return Client; }
getClient()353   const DiagnosticConsumer *getClient() const { return Client; }
354 
355   /// \brief Determine whether this \c DiagnosticsEngine object own its client.
ownsClient()356   bool ownsClient() const { return OwnsDiagClient; }
357 
358   /// \brief Return the current diagnostic client along with ownership of that
359   /// client.
takeClient()360   DiagnosticConsumer *takeClient() {
361     OwnsDiagClient = false;
362     return Client;
363   }
364 
hasSourceManager()365   bool hasSourceManager() const { return SourceMgr != 0; }
getSourceManager()366   SourceManager &getSourceManager() const {
367     assert(SourceMgr && "SourceManager not set!");
368     return *SourceMgr;
369   }
setSourceManager(SourceManager * SrcMgr)370   void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
371 
372   //===--------------------------------------------------------------------===//
373   //  DiagnosticsEngine characterization methods, used by a client to customize
374   //  how diagnostics are emitted.
375   //
376 
377   /// \brief Copies the current DiagMappings and pushes the new copy
378   /// onto the top of the stack.
379   void pushMappings(SourceLocation Loc);
380 
381   /// \brief Pops the current DiagMappings off the top of the stack,
382   /// causing the new top of the stack to be the active mappings.
383   ///
384   /// \returns \c true if the pop happens, \c false if there is only one
385   /// DiagMapping on the stack.
386   bool popMappings(SourceLocation Loc);
387 
388   /// \brief Set the diagnostic client associated with this diagnostic object.
389   ///
390   /// \param ShouldOwnClient true if the diagnostic object should take
391   /// ownership of \c client.
392   void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true);
393 
394   /// \brief Specify a limit for the number of errors we should
395   /// emit before giving up.
396   ///
397   /// Zero disables the limit.
setErrorLimit(unsigned Limit)398   void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }
399 
400   /// \brief Specify the maximum number of template instantiation
401   /// notes to emit along with a given diagnostic.
setTemplateBacktraceLimit(unsigned Limit)402   void setTemplateBacktraceLimit(unsigned Limit) {
403     TemplateBacktraceLimit = Limit;
404   }
405 
406   /// \brief Retrieve the maximum number of template instantiation
407   /// notes to emit along with a given diagnostic.
getTemplateBacktraceLimit()408   unsigned getTemplateBacktraceLimit() const {
409     return TemplateBacktraceLimit;
410   }
411 
412   /// \brief Specify the maximum number of constexpr evaluation
413   /// notes to emit along with a given diagnostic.
setConstexprBacktraceLimit(unsigned Limit)414   void setConstexprBacktraceLimit(unsigned Limit) {
415     ConstexprBacktraceLimit = Limit;
416   }
417 
418   /// \brief Retrieve the maximum number of constexpr evaluation
419   /// notes to emit along with a given diagnostic.
getConstexprBacktraceLimit()420   unsigned getConstexprBacktraceLimit() const {
421     return ConstexprBacktraceLimit;
422   }
423 
424   /// \brief When set to true, any unmapped warnings are ignored.
425   ///
426   /// If this and WarningsAsErrors are both set, then this one wins.
setIgnoreAllWarnings(bool Val)427   void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
getIgnoreAllWarnings()428   bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
429 
430   /// \brief When set to true, any unmapped ignored warnings are no longer
431   /// ignored.
432   ///
433   /// If this and IgnoreAllWarnings are both set, then that one wins.
setEnableAllWarnings(bool Val)434   void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; }
getEnableAllWarnngs()435   bool getEnableAllWarnngs() const { return EnableAllWarnings; }
436 
437   /// \brief When set to true, any warnings reported are issued as errors.
setWarningsAsErrors(bool Val)438   void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
getWarningsAsErrors()439   bool getWarningsAsErrors() const { return WarningsAsErrors; }
440 
441   /// \brief When set to true, any error reported is made a fatal error.
setErrorsAsFatal(bool Val)442   void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
getErrorsAsFatal()443   bool getErrorsAsFatal() const { return ErrorsAsFatal; }
444 
445   /// \brief When set to true mask warnings that come from system headers.
setSuppressSystemWarnings(bool Val)446   void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
getSuppressSystemWarnings()447   bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
448 
449   /// \brief Suppress all diagnostics, to silence the front end when we
450   /// know that we don't want any more diagnostics to be passed along to the
451   /// client
452   void setSuppressAllDiagnostics(bool Val = true) {
453     SuppressAllDiagnostics = Val;
454   }
getSuppressAllDiagnostics()455   bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
456 
457   /// \brief Set type eliding, to skip outputting same types occurring in
458   /// template types.
459   void setElideType(bool Val = true) { ElideType = Val; }
getElideType()460   bool getElideType() { return ElideType; }
461 
462   /// \brief Set tree printing, to outputting the template difference in a
463   /// tree format.
464   void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; }
getPrintTemplateTree()465   bool getPrintTemplateTree() { return PrintTemplateTree; }
466 
467   /// \brief Set color printing, so the type diffing will inject color markers
468   /// into the output.
469   void setShowColors(bool Val = false) { ShowColors = Val; }
getShowColors()470   bool getShowColors() { return ShowColors; }
471 
472   /// \brief Specify which overload candidates to show when overload resolution
473   /// fails.
474   ///
475   /// By default, we show all candidates.
setShowOverloads(OverloadsShown Val)476   void setShowOverloads(OverloadsShown Val) {
477     ShowOverloads = Val;
478   }
getShowOverloads()479   OverloadsShown getShowOverloads() const { return ShowOverloads; }
480 
481   /// \brief Pretend that the last diagnostic issued was ignored.
482   ///
483   /// This can be used by clients who suppress diagnostics themselves.
setLastDiagnosticIgnored()484   void setLastDiagnosticIgnored() {
485     LastDiagLevel = DiagnosticIDs::Ignored;
486   }
487 
488   /// \brief Controls whether otherwise-unmapped extension diagnostics are
489   /// mapped onto ignore/warning/error.
490   ///
491   /// This corresponds to the GCC -pedantic and -pedantic-errors option.
setExtensionHandlingBehavior(ExtensionHandling H)492   void setExtensionHandlingBehavior(ExtensionHandling H) {
493     ExtBehavior = H;
494   }
getExtensionHandlingBehavior()495   ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; }
496 
497   /// \brief Counter bumped when an __extension__  block is/ encountered.
498   ///
499   /// When non-zero, all extension diagnostics are entirely silenced, no
500   /// matter how they are mapped.
IncrementAllExtensionsSilenced()501   void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
DecrementAllExtensionsSilenced()502   void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
hasAllExtensionsSilenced()503   bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
504 
505   /// \brief This allows the client to specify that certain warnings are
506   /// ignored.
507   ///
508   /// Notes can never be mapped, errors can only be mapped to fatal, and
509   /// WARNINGs and EXTENSIONs can be mapped arbitrarily.
510   ///
511   /// \param Loc The source location that this change of diagnostic state should
512   /// take affect. It can be null if we are setting the latest state.
513   void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
514                             SourceLocation Loc);
515 
516   /// \brief Change an entire diagnostic group (e.g. "unknown-pragmas") to
517   /// have the specified mapping.
518   ///
519   /// \returns true (and ignores the request) if "Group" was unknown, false
520   /// otherwise.
521   ///
522   /// \param Loc The source location that this change of diagnostic state should
523   /// take affect. It can be null if we are setting the state from command-line.
524   bool setDiagnosticGroupMapping(StringRef Group, diag::Mapping Map,
525                                  SourceLocation Loc = SourceLocation());
526 
527   /// \brief Set the warning-as-error flag for the given diagnostic.
528   ///
529   /// This function always only operates on the current diagnostic state.
530   void setDiagnosticWarningAsError(diag::kind Diag, bool Enabled);
531 
532   /// \brief Set the warning-as-error flag for the given diagnostic group.
533   ///
534   /// This function always only operates on the current diagnostic state.
535   ///
536   /// \returns True if the given group is unknown, false otherwise.
537   bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled);
538 
539   /// \brief Set the error-as-fatal flag for the given diagnostic.
540   ///
541   /// This function always only operates on the current diagnostic state.
542   void setDiagnosticErrorAsFatal(diag::kind Diag, bool Enabled);
543 
544   /// \brief Set the error-as-fatal flag for the given diagnostic group.
545   ///
546   /// This function always only operates on the current diagnostic state.
547   ///
548   /// \returns True if the given group is unknown, false otherwise.
549   bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);
550 
551   /// \brief Add the specified mapping to all diagnostics.
552   ///
553   /// Mainly to be used by -Wno-everything to disable all warnings but allow
554   /// subsequent -W options to enable specific warnings.
555   void setMappingToAllDiagnostics(diag::Mapping Map,
556                                   SourceLocation Loc = SourceLocation());
557 
hasErrorOccurred()558   bool hasErrorOccurred() const { return ErrorOccurred; }
hasFatalErrorOccurred()559   bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
560 
561   /// \brief Determine whether any kind of unrecoverable error has occurred.
hasUnrecoverableErrorOccurred()562   bool hasUnrecoverableErrorOccurred() const {
563     return FatalErrorOccurred || UnrecoverableErrorOccurred;
564   }
565 
getNumWarnings()566   unsigned getNumWarnings() const { return NumWarnings; }
567 
setNumWarnings(unsigned NumWarnings)568   void setNumWarnings(unsigned NumWarnings) {
569     this->NumWarnings = NumWarnings;
570   }
571 
572   /// \brief Return an ID for a diagnostic with the specified message and level.
573   ///
574   /// If this is the first request for this diagnosic, it is registered and
575   /// created, otherwise the existing ID is returned.
getCustomDiagID(Level L,StringRef Message)576   unsigned getCustomDiagID(Level L, StringRef Message) {
577     return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
578   }
579 
580   /// \brief Converts a diagnostic argument (as an intptr_t) into the string
581   /// that represents it.
ConvertArgToString(ArgumentKind Kind,intptr_t Val,const char * Modifier,unsigned ModLen,const char * Argument,unsigned ArgLen,const ArgumentValue * PrevArgs,unsigned NumPrevArgs,SmallVectorImpl<char> & Output,SmallVectorImpl<intptr_t> & QualTypeVals)582   void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
583                           const char *Modifier, unsigned ModLen,
584                           const char *Argument, unsigned ArgLen,
585                           const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
586                           SmallVectorImpl<char> &Output,
587                           SmallVectorImpl<intptr_t> &QualTypeVals) const {
588     ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
589                   PrevArgs, NumPrevArgs, Output, ArgToStringCookie,
590                   QualTypeVals);
591   }
592 
SetArgToStringFn(ArgToStringFnTy Fn,void * Cookie)593   void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
594     ArgToStringFn = Fn;
595     ArgToStringCookie = Cookie;
596   }
597 
598   /// \brief Reset the state of the diagnostic object to its initial
599   /// configuration.
600   void Reset();
601 
602   //===--------------------------------------------------------------------===//
603   // DiagnosticsEngine classification and reporting interfaces.
604   //
605 
606   /// \brief Based on the way the client configured the DiagnosticsEngine
607   /// object, classify the specified diagnostic ID into a Level, consumable by
608   /// the DiagnosticConsumer.
609   ///
610   /// \param Loc The source location we are interested in finding out the
611   /// diagnostic state. Can be null in order to query the latest state.
getDiagnosticLevel(unsigned DiagID,SourceLocation Loc)612   Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
613     return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
614   }
615 
616   /// \brief Issue the message to the client.
617   ///
618   /// This actually returns an instance of DiagnosticBuilder which emits the
619   /// diagnostics (through @c ProcessDiag) when it is destroyed.
620   ///
621   /// \param DiagID A member of the @c diag::kind enum.
622   /// \param Loc Represents the source location associated with the diagnostic,
623   /// which can be an invalid location if no position information is available.
624   inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID);
625   inline DiagnosticBuilder Report(unsigned DiagID);
626 
627   void Report(const StoredDiagnostic &storedDiag);
628 
629   /// \brief Determine whethere there is already a diagnostic in flight.
isDiagnosticInFlight()630   bool isDiagnosticInFlight() const { return CurDiagID != ~0U; }
631 
632   /// \brief Set the "delayed" diagnostic that will be emitted once
633   /// the current diagnostic completes.
634   ///
635   ///  If a diagnostic is already in-flight but the front end must
636   ///  report a problem (e.g., with an inconsistent file system
637   ///  state), this routine sets a "delayed" diagnostic that will be
638   ///  emitted after the current diagnostic completes. This should
639   ///  only be used for fatal errors detected at inconvenient
640   ///  times. If emitting a delayed diagnostic causes a second delayed
641   ///  diagnostic to be introduced, that second delayed diagnostic
642   ///  will be ignored.
643   ///
644   /// \param DiagID The ID of the diagnostic being delayed.
645   ///
646   /// \param Arg1 A string argument that will be provided to the
647   /// diagnostic. A copy of this string will be stored in the
648   /// DiagnosticsEngine object itself.
649   ///
650   /// \param Arg2 A string argument that will be provided to the
651   /// diagnostic. A copy of this string will be stored in the
652   /// DiagnosticsEngine object itself.
653   void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
654                             StringRef Arg2 = "");
655 
656   /// \brief Clear out the current diagnostic.
Clear()657   void Clear() { CurDiagID = ~0U; }
658 
659 private:
660   /// \brief Report the delayed diagnostic.
661   void ReportDelayed();
662 
663   // This is private state used by DiagnosticBuilder.  We put it here instead of
664   // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
665   // object.  This implementation choice means that we can only have one
666   // diagnostic "in flight" at a time, but this seems to be a reasonable
667   // tradeoff to keep these objects small.  Assertions verify that only one
668   // diagnostic is in flight at a time.
669   friend class DiagnosticIDs;
670   friend class DiagnosticBuilder;
671   friend class Diagnostic;
672   friend class PartialDiagnostic;
673   friend class DiagnosticErrorTrap;
674 
675   /// \brief The location of the current diagnostic that is in flight.
676   SourceLocation CurDiagLoc;
677 
678   /// \brief The ID of the current diagnostic that is in flight.
679   ///
680   /// This is set to ~0U when there is no diagnostic in flight.
681   unsigned CurDiagID;
682 
683   enum {
684     /// \brief The maximum number of arguments we can hold.
685     ///
686     /// We currently only support up to 10 arguments (%0-%9).  A single
687     /// diagnostic with more than that almost certainly has to be simplified
688     /// anyway.
689     MaxArguments = 10,
690 
691     /// \brief The maximum number of ranges we can hold.
692     MaxRanges = 10,
693 
694     /// \brief The maximum number of ranges we can hold.
695     MaxFixItHints = 10
696   };
697 
698   /// \brief The number of entries in Arguments.
699   signed char NumDiagArgs;
700   /// \brief The number of ranges in the DiagRanges array.
701   unsigned char NumDiagRanges;
702   /// \brief The number of hints in the DiagFixItHints array.
703   unsigned char NumDiagFixItHints;
704 
705   /// \brief Specifies whether an argument is in DiagArgumentsStr or
706   /// in DiagArguments.
707   ///
708   /// This is an array of ArgumentKind::ArgumentKind enum values, one for each
709   /// argument.
710   unsigned char DiagArgumentsKind[MaxArguments];
711 
712   /// \brief Holds the values of each string argument for the current
713   /// diagnostic.
714   ///
715   /// This is only used when the corresponding ArgumentKind is ak_std_string.
716   std::string DiagArgumentsStr[MaxArguments];
717 
718   /// \brief The values for the various substitution positions.
719   ///
720   /// This is used when the argument is not an std::string.  The specific
721   /// value is mangled into an intptr_t and the interpretation depends on
722   /// exactly what sort of argument kind it is.
723   intptr_t DiagArgumentsVal[MaxArguments];
724 
725   /// \brief The list of ranges added to this diagnostic.
726   CharSourceRange DiagRanges[MaxRanges];
727 
728   /// \brief If valid, provides a hint with some code to insert, remove,
729   /// or modify at a particular position.
730   FixItHint DiagFixItHints[MaxFixItHints];
731 
makeMappingInfo(diag::Mapping Map,SourceLocation L)732   DiagnosticMappingInfo makeMappingInfo(diag::Mapping Map, SourceLocation L) {
733     bool isPragma = L.isValid();
734     DiagnosticMappingInfo MappingInfo = DiagnosticMappingInfo::Make(
735       Map, /*IsUser=*/true, isPragma);
736 
737     // If this is a pragma mapping, then set the diagnostic mapping flags so
738     // that we override command line options.
739     if (isPragma) {
740       MappingInfo.setNoWarningAsError(true);
741       MappingInfo.setNoErrorAsFatal(true);
742     }
743 
744     return MappingInfo;
745   }
746 
747   /// \brief Used to report a diagnostic that is finally fully formed.
748   ///
749   /// \returns true if the diagnostic was emitted, false if it was suppressed.
ProcessDiag()750   bool ProcessDiag() {
751     return Diags->ProcessDiag(*this);
752   }
753 
754   /// @name Diagnostic Emission
755   /// @{
756 protected:
757   // Sema requires access to the following functions because the current design
758   // of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to
759   // access us directly to ensure we minimize the emitted code for the common
760   // Sema::Diag() patterns.
761   friend class Sema;
762 
763   /// \brief Emit the current diagnostic and clear the diagnostic state.
764   ///
765   /// \param Force Emit the diagnostic regardless of suppression settings.
766   bool EmitCurrentDiagnostic(bool Force = false);
767 
getCurrentDiagID()768   unsigned getCurrentDiagID() const { return CurDiagID; }
769 
getCurrentDiagLoc()770   SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; }
771 
772   /// @}
773 
774   friend class ASTReader;
775   friend class ASTWriter;
776 };
777 
778 /// \brief RAII class that determines when any errors have occurred
779 /// between the time the instance was created and the time it was
780 /// queried.
781 class DiagnosticErrorTrap {
782   DiagnosticsEngine &Diag;
783   unsigned NumErrors;
784   unsigned NumUnrecoverableErrors;
785 
786 public:
DiagnosticErrorTrap(DiagnosticsEngine & Diag)787   explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag)
788     : Diag(Diag) { reset(); }
789 
790   /// \brief Determine whether any errors have occurred since this
791   /// object instance was created.
hasErrorOccurred()792   bool hasErrorOccurred() const {
793     return Diag.TrapNumErrorsOccurred > NumErrors;
794   }
795 
796   /// \brief Determine whether any unrecoverable errors have occurred since this
797   /// object instance was created.
hasUnrecoverableErrorOccurred()798   bool hasUnrecoverableErrorOccurred() const {
799     return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
800   }
801 
802   /// \brief Set to initial state of "no errors occurred".
reset()803   void reset() {
804     NumErrors = Diag.TrapNumErrorsOccurred;
805     NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
806   }
807 };
808 
809 //===----------------------------------------------------------------------===//
810 // DiagnosticBuilder
811 //===----------------------------------------------------------------------===//
812 
813 /// \brief A little helper class used to produce diagnostics.
814 ///
815 /// This is constructed by the DiagnosticsEngine::Report method, and
816 /// allows insertion of extra information (arguments and source ranges) into
817 /// the currently "in flight" diagnostic.  When the temporary for the builder
818 /// is destroyed, the diagnostic is issued.
819 ///
820 /// Note that many of these will be created as temporary objects (many call
821 /// sites), so we want them to be small and we never want their address taken.
822 /// This ensures that compilers with somewhat reasonable optimizers will promote
823 /// the common fields to registers, eliminating increments of the NumArgs field,
824 /// for example.
825 class DiagnosticBuilder {
826   mutable DiagnosticsEngine *DiagObj;
827   mutable unsigned NumArgs, NumRanges, NumFixits;
828 
829   /// \brief Status variable indicating if this diagnostic is still active.
830   ///
831   // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)),
832   // but LLVM is not currently smart enough to eliminate the null check that
833   // Emit() would end up with if we used that as our status variable.
834   mutable bool IsActive;
835 
836   /// \brief Flag indicating that this diagnostic is being emitted via a
837   /// call to ForceEmit.
838   mutable bool IsForceEmit;
839 
840   void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
841   friend class DiagnosticsEngine;
842 
DiagnosticBuilder()843   DiagnosticBuilder()
844     : DiagObj(0), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(false),
845       IsForceEmit(false) { }
846 
DiagnosticBuilder(DiagnosticsEngine * diagObj)847   explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
848     : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true),
849       IsForceEmit(false) {
850     assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!");
851   }
852 
853   friend class PartialDiagnostic;
854 
855 protected:
FlushCounts()856   void FlushCounts() {
857     DiagObj->NumDiagArgs = NumArgs;
858     DiagObj->NumDiagRanges = NumRanges;
859     DiagObj->NumDiagFixItHints = NumFixits;
860   }
861 
862   /// \brief Clear out the current diagnostic.
Clear()863   void Clear() const {
864     DiagObj = 0;
865     IsActive = false;
866     IsForceEmit = false;
867   }
868 
869   /// \brief Determine whether this diagnostic is still active.
isActive()870   bool isActive() const { return IsActive; }
871 
872   /// \brief Force the diagnostic builder to emit the diagnostic now.
873   ///
874   /// Once this function has been called, the DiagnosticBuilder object
875   /// should not be used again before it is destroyed.
876   ///
877   /// \returns true if a diagnostic was emitted, false if the
878   /// diagnostic was suppressed.
Emit()879   bool Emit() {
880     // If this diagnostic is inactive, then its soul was stolen by the copy ctor
881     // (or by a subclass, as in SemaDiagnosticBuilder).
882     if (!isActive()) return false;
883 
884     // When emitting diagnostics, we set the final argument count into
885     // the DiagnosticsEngine object.
886     FlushCounts();
887 
888     // Process the diagnostic.
889     bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit);
890 
891     // This diagnostic is dead.
892     Clear();
893 
894     return Result;
895   }
896 
897 public:
898   /// Copy constructor.  When copied, this "takes" the diagnostic info from the
899   /// input and neuters it.
DiagnosticBuilder(const DiagnosticBuilder & D)900   DiagnosticBuilder(const DiagnosticBuilder &D) {
901     DiagObj = D.DiagObj;
902     IsActive = D.IsActive;
903     IsForceEmit = D.IsForceEmit;
904     D.Clear();
905     NumArgs = D.NumArgs;
906     NumRanges = D.NumRanges;
907     NumFixits = D.NumFixits;
908   }
909 
910   /// \brief Retrieve an empty diagnostic builder.
getEmpty()911   static DiagnosticBuilder getEmpty() {
912     return DiagnosticBuilder();
913   }
914 
915   /// \brief Emits the diagnostic.
~DiagnosticBuilder()916   ~DiagnosticBuilder() {
917     Emit();
918   }
919 
920   /// \brief Forces the diagnostic to be emitted.
setForceEmit()921   const DiagnosticBuilder &setForceEmit() const {
922     IsForceEmit = true;
923     return *this;
924   }
925 
926   /// \brief Conversion of DiagnosticBuilder to bool always returns \c true.
927   ///
928   /// This allows is to be used in boolean error contexts (where \c true is
929   /// used to indicate that an error has occurred), like:
930   /// \code
931   /// return Diag(...);
932   /// \endcode
933   operator bool() const { return true; }
934 
AddString(StringRef S)935   void AddString(StringRef S) const {
936     assert(isActive() && "Clients must not add to cleared diagnostic!");
937     assert(NumArgs < DiagnosticsEngine::MaxArguments &&
938            "Too many arguments to diagnostic!");
939     DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string;
940     DiagObj->DiagArgumentsStr[NumArgs++] = S;
941   }
942 
AddTaggedVal(intptr_t V,DiagnosticsEngine::ArgumentKind Kind)943   void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
944     assert(isActive() && "Clients must not add to cleared diagnostic!");
945     assert(NumArgs < DiagnosticsEngine::MaxArguments &&
946            "Too many arguments to diagnostic!");
947     DiagObj->DiagArgumentsKind[NumArgs] = Kind;
948     DiagObj->DiagArgumentsVal[NumArgs++] = V;
949   }
950 
AddSourceRange(const CharSourceRange & R)951   void AddSourceRange(const CharSourceRange &R) const {
952     assert(isActive() && "Clients must not add to cleared diagnostic!");
953     assert(NumRanges < DiagnosticsEngine::MaxRanges &&
954            "Too many arguments to diagnostic!");
955     DiagObj->DiagRanges[NumRanges++] = R;
956   }
957 
AddFixItHint(const FixItHint & Hint)958   void AddFixItHint(const FixItHint &Hint) const {
959     assert(isActive() && "Clients must not add to cleared diagnostic!");
960     assert(NumFixits < DiagnosticsEngine::MaxFixItHints &&
961            "Too many arguments to diagnostic!");
962     DiagObj->DiagFixItHints[NumFixits++] = Hint;
963   }
964 };
965 
966 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
967                                            StringRef S) {
968   DB.AddString(S);
969   return DB;
970 }
971 
972 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
973                                            const char *Str) {
974   DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
975                   DiagnosticsEngine::ak_c_string);
976   return DB;
977 }
978 
979 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
980   DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
981   return DB;
982 }
983 
984 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
985   DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
986   return DB;
987 }
988 
989 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
990                                            unsigned I) {
991   DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
992   return DB;
993 }
994 
995 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
996                                            const IdentifierInfo *II) {
997   DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
998                   DiagnosticsEngine::ak_identifierinfo);
999   return DB;
1000 }
1001 
1002 // Adds a DeclContext to the diagnostic. The enable_if template magic is here
1003 // so that we only match those arguments that are (statically) DeclContexts;
1004 // other arguments that derive from DeclContext (e.g., RecordDecls) will not
1005 // match.
1006 template<typename T>
1007 inline
1008 typename llvm::enable_if<llvm::is_same<T, DeclContext>,
1009                          const DiagnosticBuilder &>::type
1010 operator<<(const DiagnosticBuilder &DB, T *DC) {
1011   DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
1012                   DiagnosticsEngine::ak_declcontext);
1013   return DB;
1014 }
1015 
1016 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1017                                            const SourceRange &R) {
1018   DB.AddSourceRange(CharSourceRange::getTokenRange(R));
1019   return DB;
1020 }
1021 
1022 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1023                                            const CharSourceRange &R) {
1024   DB.AddSourceRange(R);
1025   return DB;
1026 }
1027 
1028 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1029                                            const FixItHint &Hint) {
1030   if (!Hint.isNull())
1031     DB.AddFixItHint(Hint);
1032   return DB;
1033 }
1034 
Report(SourceLocation Loc,unsigned DiagID)1035 inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
1036                                             unsigned DiagID){
1037   assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
1038   CurDiagLoc = Loc;
1039   CurDiagID = DiagID;
1040   return DiagnosticBuilder(this);
1041 }
Report(unsigned DiagID)1042 inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
1043   return Report(SourceLocation(), DiagID);
1044 }
1045 
1046 //===----------------------------------------------------------------------===//
1047 // Diagnostic
1048 //===----------------------------------------------------------------------===//
1049 
1050 /// A little helper class (which is basically a smart pointer that forwards
1051 /// info from DiagnosticsEngine) that allows clients to enquire about the
1052 /// currently in-flight diagnostic.
1053 class Diagnostic {
1054   const DiagnosticsEngine *DiagObj;
1055   StringRef StoredDiagMessage;
1056 public:
Diagnostic(const DiagnosticsEngine * DO)1057   explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {}
Diagnostic(const DiagnosticsEngine * DO,StringRef storedDiagMessage)1058   Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage)
1059     : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
1060 
getDiags()1061   const DiagnosticsEngine *getDiags() const { return DiagObj; }
getID()1062   unsigned getID() const { return DiagObj->CurDiagID; }
getLocation()1063   const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
hasSourceManager()1064   bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
getSourceManager()1065   SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}
1066 
getNumArgs()1067   unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
1068 
1069   /// \brief Return the kind of the specified index.
1070   ///
1071   /// Based on the kind of argument, the accessors below can be used to get
1072   /// the value.
1073   ///
1074   /// \pre Idx < getNumArgs()
getArgKind(unsigned Idx)1075   DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const {
1076     assert(Idx < getNumArgs() && "Argument index out of range!");
1077     return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
1078   }
1079 
1080   /// \brief Return the provided argument string specified by \p Idx.
1081   /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string
getArgStdStr(unsigned Idx)1082   const std::string &getArgStdStr(unsigned Idx) const {
1083     assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
1084            "invalid argument accessor!");
1085     return DiagObj->DiagArgumentsStr[Idx];
1086   }
1087 
1088   /// \brief Return the specified C string argument.
1089   /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string
getArgCStr(unsigned Idx)1090   const char *getArgCStr(unsigned Idx) const {
1091     assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
1092            "invalid argument accessor!");
1093     return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
1094   }
1095 
1096   /// \brief Return the specified signed integer argument.
1097   /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint
getArgSInt(unsigned Idx)1098   int getArgSInt(unsigned Idx) const {
1099     assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
1100            "invalid argument accessor!");
1101     return (int)DiagObj->DiagArgumentsVal[Idx];
1102   }
1103 
1104   /// \brief Return the specified unsigned integer argument.
1105   /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint
getArgUInt(unsigned Idx)1106   unsigned getArgUInt(unsigned Idx) const {
1107     assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
1108            "invalid argument accessor!");
1109     return (unsigned)DiagObj->DiagArgumentsVal[Idx];
1110   }
1111 
1112   /// \brief Return the specified IdentifierInfo argument.
1113   /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo
getArgIdentifier(unsigned Idx)1114   const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
1115     assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
1116            "invalid argument accessor!");
1117     return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
1118   }
1119 
1120   /// \brief Return the specified non-string argument in an opaque form.
1121   /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string
getRawArg(unsigned Idx)1122   intptr_t getRawArg(unsigned Idx) const {
1123     assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
1124            "invalid argument accessor!");
1125     return DiagObj->DiagArgumentsVal[Idx];
1126   }
1127 
1128   /// \brief Return the number of source ranges associated with this diagnostic.
getNumRanges()1129   unsigned getNumRanges() const {
1130     return DiagObj->NumDiagRanges;
1131   }
1132 
1133   /// \pre Idx < getNumRanges()
getRange(unsigned Idx)1134   const CharSourceRange &getRange(unsigned Idx) const {
1135     assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
1136     return DiagObj->DiagRanges[Idx];
1137   }
1138 
1139   /// \brief Return an array reference for this diagnostic's ranges.
getRanges()1140   ArrayRef<CharSourceRange> getRanges() const {
1141     return llvm::makeArrayRef(DiagObj->DiagRanges, DiagObj->NumDiagRanges);
1142   }
1143 
getNumFixItHints()1144   unsigned getNumFixItHints() const {
1145     return DiagObj->NumDiagFixItHints;
1146   }
1147 
getFixItHint(unsigned Idx)1148   const FixItHint &getFixItHint(unsigned Idx) const {
1149     assert(Idx < getNumFixItHints() && "Invalid index!");
1150     return DiagObj->DiagFixItHints[Idx];
1151   }
1152 
getFixItHints()1153   const FixItHint *getFixItHints() const {
1154     return getNumFixItHints()? DiagObj->DiagFixItHints : 0;
1155   }
1156 
1157   /// \brief Format this diagnostic into a string, substituting the
1158   /// formal arguments into the %0 slots.
1159   ///
1160   /// The result is appended onto the \p OutStr array.
1161   void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;
1162 
1163   /// \brief Format the given format-string into the output buffer using the
1164   /// arguments stored in this diagnostic.
1165   void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
1166                         SmallVectorImpl<char> &OutStr) const;
1167 };
1168 
1169 /**
1170  * \brief Represents a diagnostic in a form that can be retained until its
1171  * corresponding source manager is destroyed.
1172  */
1173 class StoredDiagnostic {
1174   unsigned ID;
1175   DiagnosticsEngine::Level Level;
1176   FullSourceLoc Loc;
1177   std::string Message;
1178   std::vector<CharSourceRange> Ranges;
1179   std::vector<FixItHint> FixIts;
1180 
1181 public:
1182   StoredDiagnostic();
1183   StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
1184   StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1185                    StringRef Message);
1186   StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1187                    StringRef Message, FullSourceLoc Loc,
1188                    ArrayRef<CharSourceRange> Ranges,
1189                    ArrayRef<FixItHint> Fixits);
1190   ~StoredDiagnostic();
1191 
1192   /// \brief Evaluates true when this object stores a diagnostic.
1193   operator bool() const { return Message.size() > 0; }
1194 
getID()1195   unsigned getID() const { return ID; }
getLevel()1196   DiagnosticsEngine::Level getLevel() const { return Level; }
getLocation()1197   const FullSourceLoc &getLocation() const { return Loc; }
getMessage()1198   StringRef getMessage() const { return Message; }
1199 
setLocation(FullSourceLoc Loc)1200   void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
1201 
1202   typedef std::vector<CharSourceRange>::const_iterator range_iterator;
range_begin()1203   range_iterator range_begin() const { return Ranges.begin(); }
range_end()1204   range_iterator range_end() const { return Ranges.end(); }
range_size()1205   unsigned range_size() const { return Ranges.size(); }
1206 
getRanges()1207   ArrayRef<CharSourceRange> getRanges() const {
1208     return llvm::makeArrayRef(Ranges);
1209   }
1210 
1211 
1212   typedef std::vector<FixItHint>::const_iterator fixit_iterator;
fixit_begin()1213   fixit_iterator fixit_begin() const { return FixIts.begin(); }
fixit_end()1214   fixit_iterator fixit_end() const { return FixIts.end(); }
fixit_size()1215   unsigned fixit_size() const { return FixIts.size(); }
1216 
getFixIts()1217   ArrayRef<FixItHint> getFixIts() const {
1218     return llvm::makeArrayRef(FixIts);
1219   }
1220 };
1221 
1222 /// \brief Abstract interface, implemented by clients of the front-end, which
1223 /// formats and prints fully processed diagnostics.
1224 class DiagnosticConsumer {
1225 protected:
1226   unsigned NumWarnings;       ///< Number of warnings reported
1227   unsigned NumErrors;         ///< Number of errors reported
1228 
1229 public:
DiagnosticConsumer()1230   DiagnosticConsumer() : NumWarnings(0), NumErrors(0) { }
1231 
getNumErrors()1232   unsigned getNumErrors() const { return NumErrors; }
getNumWarnings()1233   unsigned getNumWarnings() const { return NumWarnings; }
clear()1234   virtual void clear() { NumWarnings = NumErrors = 0; }
1235 
1236   virtual ~DiagnosticConsumer();
1237 
1238   /// \brief Callback to inform the diagnostic client that processing
1239   /// of a source file is beginning.
1240   ///
1241   /// Note that diagnostics may be emitted outside the processing of a source
1242   /// file, for example during the parsing of command line options. However,
1243   /// diagnostics with source range information are required to only be emitted
1244   /// in between BeginSourceFile() and EndSourceFile().
1245   ///
1246   /// \param LangOpts The language options for the source file being processed.
1247   /// \param PP The preprocessor object being used for the source; this is
1248   /// optional, e.g., it may not be present when processing AST source files.
1249   virtual void BeginSourceFile(const LangOptions &LangOpts,
1250                                const Preprocessor *PP = 0) {}
1251 
1252   /// \brief Callback to inform the diagnostic client that processing
1253   /// of a source file has ended.
1254   ///
1255   /// The diagnostic client should assume that any objects made available via
1256   /// BeginSourceFile() are inaccessible.
EndSourceFile()1257   virtual void EndSourceFile() {}
1258 
1259   /// \brief Callback to inform the diagnostic client that processing of all
1260   /// source files has ended.
finish()1261   virtual void finish() {}
1262 
1263   /// \brief Indicates whether the diagnostics handled by this
1264   /// DiagnosticConsumer should be included in the number of diagnostics
1265   /// reported by DiagnosticsEngine.
1266   ///
1267   /// The default implementation returns true.
1268   virtual bool IncludeInDiagnosticCounts() const;
1269 
1270   /// \brief Handle this diagnostic, reporting it to the user or
1271   /// capturing it to a log as needed.
1272   ///
1273   /// The default implementation just keeps track of the total number of
1274   /// warnings and errors.
1275   virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1276                                 const Diagnostic &Info);
1277 
1278   /// \brief Clone the diagnostic consumer, producing an equivalent consumer
1279   /// that can be used in a different context.
1280   virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const = 0;
1281 };
1282 
1283 /// \brief A diagnostic client that ignores all diagnostics.
1284 class IgnoringDiagConsumer : public DiagnosticConsumer {
1285   virtual void anchor();
HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,const Diagnostic & Info)1286   void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1287                         const Diagnostic &Info) {
1288     // Just ignore it.
1289   }
clone(DiagnosticsEngine & Diags)1290   DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
1291     return new IgnoringDiagConsumer();
1292   }
1293 };
1294 
1295 // Struct used for sending info about how a type should be printed.
1296 struct TemplateDiffTypes {
1297   intptr_t FromType;
1298   intptr_t ToType;
1299   unsigned PrintTree : 1;
1300   unsigned PrintFromType : 1;
1301   unsigned ElideType : 1;
1302   unsigned ShowColors : 1;
1303   // The printer sets this variable to true if the template diff was used.
1304   unsigned TemplateDiffUsed : 1;
1305 };
1306 
1307 /// Special character that the diagnostic printer will use to toggle the bold
1308 /// attribute.  The character itself will be not be printed.
1309 const char ToggleHighlight = 127;
1310 
1311 }  // end namespace clang
1312 
1313 #endif
1314