Diagnostic.h revision 249423
1193326Sed//===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- C++ -*-===//
2193326Sed//
3193326Sed//                     The LLVM Compiler Infrastructure
4193326Sed//
5193326Sed// This file is distributed under the University of Illinois Open Source
6193326Sed// License. See LICENSE.TXT for details.
7193326Sed//
8193326Sed//===----------------------------------------------------------------------===//
9239462Sdim///
10239462Sdim/// \file
11239462Sdim/// \brief Defines the Diagnostic-related interfaces.
12239462Sdim///
13193326Sed//===----------------------------------------------------------------------===//
14193326Sed
15193326Sed#ifndef LLVM_CLANG_DIAGNOSTIC_H
16193326Sed#define LLVM_CLANG_DIAGNOSTIC_H
17193326Sed
18218893Sdim#include "clang/Basic/DiagnosticIDs.h"
19243830Sdim#include "clang/Basic/DiagnosticOptions.h"
20193326Sed#include "clang/Basic/SourceLocation.h"
21226633Sdim#include "llvm/ADT/ArrayRef.h"
22218893Sdim#include "llvm/ADT/DenseMap.h"
23206275Srdivacky#include "llvm/ADT/IntrusiveRefCntPtr.h"
24212904Sdim#include "llvm/ADT/OwningPtr.h"
25198092Srdivacky#include "llvm/Support/type_traits.h"
26249423Sdim#include <list>
27198092Srdivacky#include <vector>
28193326Sed
29193326Sednamespace clang {
30226633Sdim  class DiagnosticConsumer;
31198092Srdivacky  class DiagnosticBuilder;
32243830Sdim  class DiagnosticOptions;
33193326Sed  class IdentifierInfo;
34218893Sdim  class DeclContext;
35193326Sed  class LangOptions;
36199482Srdivacky  class Preprocessor;
37218893Sdim  class DiagnosticErrorTrap;
38223017Sdim  class StoredDiagnostic;
39198092Srdivacky
40193326Sed/// \brief Annotates a diagnostic with some code that should be
41193326Sed/// inserted, removed, or replaced to fix the problem.
42193326Sed///
43193326Sed/// This kind of hint should be used when we are certain that the
44193326Sed/// introduction, removal, or modification of a particular (small!)
45193326Sed/// amount of code will correct a compilation error. The compiler
46193326Sed/// should also provide full recovery from such errors, such that
47193326Sed/// suppressing the diagnostic output can still result in successful
48193326Sed/// compilation.
49206084Srdivackyclass FixItHint {
50193326Sedpublic:
51212904Sdim  /// \brief Code that should be replaced to correct the error. Empty for an
52212904Sdim  /// insertion hint.
53210299Sed  CharSourceRange RemoveRange;
54193326Sed
55234353Sdim  /// \brief Code in the specific range that should be inserted in the insertion
56234353Sdim  /// location.
57234353Sdim  CharSourceRange InsertFromRange;
58234353Sdim
59193326Sed  /// \brief The actual code to insert at the insertion location, as a
60193326Sed  /// string.
61193326Sed  std::string CodeToInsert;
62193326Sed
63234353Sdim  bool BeforePreviousInsertions;
64234353Sdim
65193326Sed  /// \brief Empty code modification hint, indicating that no code
66193326Sed  /// modification is known.
67234353Sdim  FixItHint() : BeforePreviousInsertions(false) { }
68193326Sed
69199482Srdivacky  bool isNull() const {
70212904Sdim    return !RemoveRange.isValid();
71199482Srdivacky  }
72199482Srdivacky
73193326Sed  /// \brief Create a code modification hint that inserts the given
74193326Sed  /// code string at a specific location.
75206084Srdivacky  static FixItHint CreateInsertion(SourceLocation InsertionLoc,
76234353Sdim                                   StringRef Code,
77234353Sdim                                   bool BeforePreviousInsertions = false) {
78206084Srdivacky    FixItHint Hint;
79212904Sdim    Hint.RemoveRange =
80249423Sdim      CharSourceRange::getCharRange(InsertionLoc, InsertionLoc);
81193326Sed    Hint.CodeToInsert = Code;
82234353Sdim    Hint.BeforePreviousInsertions = BeforePreviousInsertions;
83193326Sed    return Hint;
84193326Sed  }
85234353Sdim
86234353Sdim  /// \brief Create a code modification hint that inserts the given
87239462Sdim  /// code from \p FromRange at a specific location.
88234353Sdim  static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc,
89234353Sdim                                            CharSourceRange FromRange,
90234353Sdim                                        bool BeforePreviousInsertions = false) {
91234353Sdim    FixItHint Hint;
92234353Sdim    Hint.RemoveRange =
93249423Sdim      CharSourceRange::getCharRange(InsertionLoc, InsertionLoc);
94234353Sdim    Hint.InsertFromRange = FromRange;
95234353Sdim    Hint.BeforePreviousInsertions = BeforePreviousInsertions;
96234353Sdim    return Hint;
97234353Sdim  }
98193326Sed
99193326Sed  /// \brief Create a code modification hint that removes the given
100193326Sed  /// source range.
101210299Sed  static FixItHint CreateRemoval(CharSourceRange RemoveRange) {
102206084Srdivacky    FixItHint Hint;
103193326Sed    Hint.RemoveRange = RemoveRange;
104193326Sed    return Hint;
105193326Sed  }
106210299Sed  static FixItHint CreateRemoval(SourceRange RemoveRange) {
107210299Sed    return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange));
108210299Sed  }
109210299Sed
110193326Sed  /// \brief Create a code modification hint that replaces the given
111193326Sed  /// source range with the given code string.
112210299Sed  static FixItHint CreateReplacement(CharSourceRange RemoveRange,
113226633Sdim                                     StringRef Code) {
114206084Srdivacky    FixItHint Hint;
115193326Sed    Hint.RemoveRange = RemoveRange;
116193326Sed    Hint.CodeToInsert = Code;
117193326Sed    return Hint;
118193326Sed  }
119210299Sed
120210299Sed  static FixItHint CreateReplacement(SourceRange RemoveRange,
121226633Sdim                                     StringRef Code) {
122210299Sed    return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
123210299Sed  }
124193326Sed};
125193326Sed
126239462Sdim/// \brief Concrete class used by the front-end to report problems and issues.
127239462Sdim///
128239462Sdim/// This massages the diagnostics (e.g. handling things like "report warnings
129239462Sdim/// as errors" and passes them off to the DiagnosticConsumer for reporting to
130239462Sdim/// the user. DiagnosticsEngine is tied to one translation unit and one
131239462Sdim/// SourceManager.
132234353Sdimclass DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
133193326Sedpublic:
134239462Sdim  /// \brief The level of the diagnostic, after it has been through mapping.
135193326Sed  enum Level {
136218893Sdim    Ignored = DiagnosticIDs::Ignored,
137218893Sdim    Note = DiagnosticIDs::Note,
138218893Sdim    Warning = DiagnosticIDs::Warning,
139218893Sdim    Error = DiagnosticIDs::Error,
140218893Sdim    Fatal = DiagnosticIDs::Fatal
141193326Sed  };
142198092Srdivacky
143239462Sdim  /// \brief How do we handle otherwise-unmapped extension?
144239462Sdim  ///
145239462Sdim  /// This is controlled by -pedantic and -pedantic-errors.
146193326Sed  enum ExtensionHandling {
147193326Sed    Ext_Ignore, Ext_Warn, Ext_Error
148193326Sed  };
149198092Srdivacky
150193326Sed  enum ArgumentKind {
151239462Sdim    ak_std_string,      ///< std::string
152239462Sdim    ak_c_string,        ///< const char *
153239462Sdim    ak_sint,            ///< int
154239462Sdim    ak_uint,            ///< unsigned
155239462Sdim    ak_identifierinfo,  ///< IdentifierInfo
156239462Sdim    ak_qualtype,        ///< QualType
157239462Sdim    ak_declarationname, ///< DeclarationName
158239462Sdim    ak_nameddecl,       ///< NamedDecl *
159239462Sdim    ak_nestednamespec,  ///< NestedNameSpecifier *
160239462Sdim    ak_declcontext,     ///< DeclContext *
161239462Sdim    ak_qualtype_pair    ///< pair<QualType, QualType>
162193326Sed  };
163210299Sed
164239462Sdim  /// \brief Represents on argument value, which is a union discriminated
165239462Sdim  /// by ArgumentKind, with a value.
166198398Srdivacky  typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
167193326Sed
168198092Srdivackyprivate:
169193326Sed  unsigned char AllExtensionsSilenced; // Used by __extension__
170193326Sed  bool IgnoreAllWarnings;        // Ignore all warnings: -w
171226633Sdim  bool WarningsAsErrors;         // Treat warnings like errors.
172226633Sdim  bool EnableAllWarnings;        // Enable all warnings.
173201361Srdivacky  bool ErrorsAsFatal;            // Treat errors like fatal errors.
174193326Sed  bool SuppressSystemWarnings;   // Suppress warnings in system headers.
175198092Srdivacky  bool SuppressAllDiagnostics;   // Suppress all diagnostics.
176239462Sdim  bool ElideType;                // Elide common types of templates.
177239462Sdim  bool PrintTemplateTree;        // Print a tree when comparing templates.
178249423Sdim  bool WarnOnSpellCheck;         // Emit warning when spellcheck is initiated.
179239462Sdim  bool ShowColors;               // Color printing is enabled.
180210299Sed  OverloadsShown ShowOverloads;  // Which overload candidates to show.
181207619Srdivacky  unsigned ErrorLimit;           // Cap of # errors emitted, 0 -> no limit.
182207619Srdivacky  unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
183207619Srdivacky                                   // 0 -> no limit.
184234353Sdim  unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation
185234353Sdim                                    // backtrace stack, 0 -> no limit.
186193326Sed  ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
187234353Sdim  IntrusiveRefCntPtr<DiagnosticIDs> Diags;
188243830Sdim  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
189226633Sdim  DiagnosticConsumer *Client;
190218893Sdim  bool OwnsDiagClient;
191218893Sdim  SourceManager *SourceMgr;
192218893Sdim
193239462Sdim  /// \brief Mapping information for diagnostics.
194218893Sdim  ///
195239462Sdim  /// Mapping info is packed into four bits per diagnostic.  The low three
196239462Sdim  /// bits are the mapping (an instance of diag::Mapping), or zero if unset.
197239462Sdim  /// The high bit is set when the mapping was established as a user mapping.
198239462Sdim  /// If the high bit is clear, then the low bits are set to the default
199239462Sdim  /// value, and should be mapped with -pedantic, -Werror, etc.
200239462Sdim  ///
201218893Sdim  /// A new DiagState is created and kept around when diagnostic pragmas modify
202218893Sdim  /// the state so that we know what is the diagnostic state at any given
203218893Sdim  /// source location.
204218893Sdim  class DiagState {
205226633Sdim    llvm::DenseMap<unsigned, DiagnosticMappingInfo> DiagMap;
206198092Srdivacky
207212904Sdim  public:
208226633Sdim    typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::iterator
209226633Sdim      iterator;
210226633Sdim    typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::const_iterator
211226633Sdim      const_iterator;
212212904Sdim
213226633Sdim    void setMappingInfo(diag::kind Diag, DiagnosticMappingInfo Info) {
214226633Sdim      DiagMap[Diag] = Info;
215212904Sdim    }
216218893Sdim
217226633Sdim    DiagnosticMappingInfo &getOrAddMappingInfo(diag::kind Diag);
218226633Sdim
219226633Sdim    const_iterator begin() const { return DiagMap.begin(); }
220226633Sdim    const_iterator end() const { return DiagMap.end(); }
221212904Sdim  };
222212904Sdim
223218893Sdim  /// \brief Keeps and automatically disposes all DiagStates that we create.
224218893Sdim  std::list<DiagState> DiagStates;
225198092Srdivacky
226218893Sdim  /// \brief Represents a point in source where the diagnostic state was
227239462Sdim  /// modified because of a pragma.
228239462Sdim  ///
229239462Sdim  /// 'Loc' can be null if the point represents the diagnostic state
230239462Sdim  /// modifications done through the command-line.
231218893Sdim  struct DiagStatePoint {
232218893Sdim    DiagState *State;
233218893Sdim    FullSourceLoc Loc;
234218893Sdim    DiagStatePoint(DiagState *State, FullSourceLoc Loc)
235218893Sdim      : State(State), Loc(Loc) { }
236218893Sdim
237218893Sdim    bool operator<(const DiagStatePoint &RHS) const {
238218893Sdim      // If Loc is invalid it means it came from <command-line>, in which case
239218893Sdim      // we regard it as coming before any valid source location.
240218893Sdim      if (RHS.Loc.isInvalid())
241218893Sdim        return false;
242218893Sdim      if (Loc.isInvalid())
243218893Sdim        return true;
244218893Sdim      return Loc.isBeforeInTranslationUnitThan(RHS.Loc);
245218893Sdim    }
246218893Sdim  };
247218893Sdim
248239462Sdim  /// \brief A sorted vector of all DiagStatePoints representing changes in
249239462Sdim  /// diagnostic state due to diagnostic pragmas.
250239462Sdim  ///
251239462Sdim  /// The vector is always sorted according to the SourceLocation of the
252239462Sdim  /// DiagStatePoint.
253218893Sdim  typedef std::vector<DiagStatePoint> DiagStatePointsTy;
254218893Sdim  mutable DiagStatePointsTy DiagStatePoints;
255218893Sdim
256218893Sdim  /// \brief Keeps the DiagState that was active during each diagnostic 'push'
257218893Sdim  /// so we can get back at it when we 'pop'.
258218893Sdim  std::vector<DiagState *> DiagStateOnPushStack;
259218893Sdim
260218893Sdim  DiagState *GetCurDiagState() const {
261218893Sdim    assert(!DiagStatePoints.empty());
262218893Sdim    return DiagStatePoints.back().State;
263218893Sdim  }
264218893Sdim
265218893Sdim  void PushDiagStatePoint(DiagState *State, SourceLocation L) {
266239462Sdim    FullSourceLoc Loc(L, getSourceManager());
267218893Sdim    // Make sure that DiagStatePoints is always sorted according to Loc.
268239462Sdim    assert(Loc.isValid() && "Adding invalid loc point");
269239462Sdim    assert(!DiagStatePoints.empty() &&
270239462Sdim           (DiagStatePoints.back().Loc.isInvalid() ||
271218893Sdim            DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) &&
272218893Sdim           "Previous point loc comes after or is the same as new one");
273239462Sdim    DiagStatePoints.push_back(DiagStatePoint(State, Loc));
274218893Sdim  }
275218893Sdim
276218893Sdim  /// \brief Finds the DiagStatePoint that contains the diagnostic state of
277218893Sdim  /// the given source location.
278218893Sdim  DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
279218893Sdim
280239462Sdim  /// \brief Sticky flag set to \c true when an error is emitted.
281193326Sed  bool ErrorOccurred;
282239462Sdim
283249423Sdim  /// \brief Sticky flag set to \c true when an "uncompilable error" occurs.
284249423Sdim  /// I.e. an error that was not upgraded from a warning by -Werror.
285249423Sdim  bool UncompilableErrorOccurred;
286249423Sdim
287239462Sdim  /// \brief Sticky flag set to \c true when a fatal error is emitted.
288193326Sed  bool FatalErrorOccurred;
289198092Srdivacky
290224145Sdim  /// \brief Indicates that an unrecoverable error has occurred.
291224145Sdim  bool UnrecoverableErrorOccurred;
292224145Sdim
293226633Sdim  /// \brief Counts for DiagnosticErrorTrap to check whether an error occurred
294224145Sdim  /// during a parsing section, e.g. during parsing a function.
295226633Sdim  unsigned TrapNumErrorsOccurred;
296226633Sdim  unsigned TrapNumUnrecoverableErrorsOccurred;
297224145Sdim
298239462Sdim  /// \brief The level of the last diagnostic emitted.
299239462Sdim  ///
300239462Sdim  /// This is used to emit continuation diagnostics with the same level as the
301193326Sed  /// diagnostic that they follow.
302218893Sdim  DiagnosticIDs::Level LastDiagLevel;
303193326Sed
304239462Sdim  unsigned NumWarnings;         ///< Number of warnings reported
305239462Sdim  unsigned NumErrors;           ///< Number of errors reported
306239462Sdim  unsigned NumErrorsSuppressed; ///< Number of errors suppressed
307193326Sed
308239462Sdim  /// \brief A function pointer that converts an opaque diagnostic
309239462Sdim  /// argument to a strings.
310198398Srdivacky  ///
311239462Sdim  /// This takes the modifiers and argument that was present in the diagnostic.
312239462Sdim  ///
313198398Srdivacky  /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
314198398Srdivacky  /// arguments formatted for this diagnostic.  Implementations of this function
315198398Srdivacky  /// can use this information to avoid redundancy across arguments.
316198398Srdivacky  ///
317193326Sed  /// This is a hack to avoid a layering violation between libbasic and libsema.
318224145Sdim  typedef void (*ArgToStringFnTy)(
319224145Sdim      ArgumentKind Kind, intptr_t Val,
320224145Sdim      const char *Modifier, unsigned ModifierLen,
321224145Sdim      const char *Argument, unsigned ArgumentLen,
322224145Sdim      const ArgumentValue *PrevArgs,
323224145Sdim      unsigned NumPrevArgs,
324226633Sdim      SmallVectorImpl<char> &Output,
325224145Sdim      void *Cookie,
326234353Sdim      ArrayRef<intptr_t> QualTypeVals);
327193326Sed  void *ArgToStringCookie;
328193326Sed  ArgToStringFnTy ArgToStringFn;
329206084Srdivacky
330206084Srdivacky  /// \brief ID of the "delayed" diagnostic, which is a (typically
331206084Srdivacky  /// fatal) diagnostic that had to be delayed because it was found
332206084Srdivacky  /// while emitting another diagnostic.
333206084Srdivacky  unsigned DelayedDiagID;
334206084Srdivacky
335206084Srdivacky  /// \brief First string argument for the delayed diagnostic.
336206084Srdivacky  std::string DelayedDiagArg1;
337206084Srdivacky
338206084Srdivacky  /// \brief Second string argument for the delayed diagnostic.
339206084Srdivacky  std::string DelayedDiagArg2;
340206084Srdivacky
341193326Sedpublic:
342226633Sdim  explicit DiagnosticsEngine(
343234353Sdim                      const IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
344243830Sdim                      DiagnosticOptions *DiagOpts,
345226633Sdim                      DiagnosticConsumer *client = 0,
346218893Sdim                      bool ShouldOwnClient = true);
347226633Sdim  ~DiagnosticsEngine();
348198092Srdivacky
349234353Sdim  const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
350218893Sdim    return Diags;
351218893Sdim  }
352218893Sdim
353243830Sdim  /// \brief Retrieve the diagnostic options.
354243830Sdim  DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; }
355243830Sdim
356226633Sdim  DiagnosticConsumer *getClient() { return Client; }
357226633Sdim  const DiagnosticConsumer *getClient() const { return Client; }
358218893Sdim
359226633Sdim  /// \brief Determine whether this \c DiagnosticsEngine object own its client.
360226633Sdim  bool ownsClient() const { return OwnsDiagClient; }
361226633Sdim
362218893Sdim  /// \brief Return the current diagnostic client along with ownership of that
363218893Sdim  /// client.
364226633Sdim  DiagnosticConsumer *takeClient() {
365218893Sdim    OwnsDiagClient = false;
366218893Sdim    return Client;
367218893Sdim  }
368218893Sdim
369218893Sdim  bool hasSourceManager() const { return SourceMgr != 0; }
370218893Sdim  SourceManager &getSourceManager() const {
371218893Sdim    assert(SourceMgr && "SourceManager not set!");
372218893Sdim    return *SourceMgr;
373218893Sdim  }
374218893Sdim  void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
375218893Sdim
376193326Sed  //===--------------------------------------------------------------------===//
377226633Sdim  //  DiagnosticsEngine characterization methods, used by a client to customize
378226633Sdim  //  how diagnostics are emitted.
379193326Sed  //
380198092Srdivacky
381239462Sdim  /// \brief Copies the current DiagMappings and pushes the new copy
382198092Srdivacky  /// onto the top of the stack.
383218893Sdim  void pushMappings(SourceLocation Loc);
384198092Srdivacky
385239462Sdim  /// \brief Pops the current DiagMappings off the top of the stack,
386239462Sdim  /// causing the new top of the stack to be the active mappings.
387239462Sdim  ///
388239462Sdim  /// \returns \c true if the pop happens, \c false if there is only one
389239462Sdim  /// DiagMapping on the stack.
390218893Sdim  bool popMappings(SourceLocation Loc);
391198092Srdivacky
392212904Sdim  /// \brief Set the diagnostic client associated with this diagnostic object.
393212904Sdim  ///
394218893Sdim  /// \param ShouldOwnClient true if the diagnostic object should take
395218893Sdim  /// ownership of \c client.
396226633Sdim  void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true);
397193326Sed
398239462Sdim  /// \brief Specify a limit for the number of errors we should
399239462Sdim  /// emit before giving up.
400239462Sdim  ///
401239462Sdim  /// Zero disables the limit.
402207619Srdivacky  void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }
403207619Srdivacky
404207619Srdivacky  /// \brief Specify the maximum number of template instantiation
405207619Srdivacky  /// notes to emit along with a given diagnostic.
406207619Srdivacky  void setTemplateBacktraceLimit(unsigned Limit) {
407207619Srdivacky    TemplateBacktraceLimit = Limit;
408207619Srdivacky  }
409234353Sdim
410207619Srdivacky  /// \brief Retrieve the maximum number of template instantiation
411234353Sdim  /// notes to emit along with a given diagnostic.
412207619Srdivacky  unsigned getTemplateBacktraceLimit() const {
413207619Srdivacky    return TemplateBacktraceLimit;
414207619Srdivacky  }
415234353Sdim
416234353Sdim  /// \brief Specify the maximum number of constexpr evaluation
417234353Sdim  /// notes to emit along with a given diagnostic.
418234353Sdim  void setConstexprBacktraceLimit(unsigned Limit) {
419234353Sdim    ConstexprBacktraceLimit = Limit;
420234353Sdim  }
421234353Sdim
422234353Sdim  /// \brief Retrieve the maximum number of constexpr evaluation
423234353Sdim  /// notes to emit along with a given diagnostic.
424234353Sdim  unsigned getConstexprBacktraceLimit() const {
425234353Sdim    return ConstexprBacktraceLimit;
426234353Sdim  }
427234353Sdim
428239462Sdim  /// \brief When set to true, any unmapped warnings are ignored.
429239462Sdim  ///
430239462Sdim  /// If this and WarningsAsErrors are both set, then this one wins.
431193326Sed  void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
432193326Sed  bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
433198092Srdivacky
434239462Sdim  /// \brief When set to true, any unmapped ignored warnings are no longer
435239462Sdim  /// ignored.
436239462Sdim  ///
437239462Sdim  /// If this and IgnoreAllWarnings are both set, then that one wins.
438226633Sdim  void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; }
439249423Sdim  bool getEnableAllWarnings() const { return EnableAllWarnings; }
440249423Sdim
441239462Sdim  /// \brief When set to true, any warnings reported are issued as errors.
442193326Sed  void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
443193326Sed  bool getWarningsAsErrors() const { return WarningsAsErrors; }
444198092Srdivacky
445239462Sdim  /// \brief When set to true, any error reported is made a fatal error.
446201361Srdivacky  void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
447201361Srdivacky  bool getErrorsAsFatal() const { return ErrorsAsFatal; }
448201361Srdivacky
449239462Sdim  /// \brief When set to true mask warnings that come from system headers.
450193326Sed  void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
451193326Sed  bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
452193326Sed
453198092Srdivacky  /// \brief Suppress all diagnostics, to silence the front end when we
454198092Srdivacky  /// know that we don't want any more diagnostics to be passed along to the
455198092Srdivacky  /// client
456198092Srdivacky  void setSuppressAllDiagnostics(bool Val = true) {
457198092Srdivacky    SuppressAllDiagnostics = Val;
458198092Srdivacky  }
459198092Srdivacky  bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
460239462Sdim
461239462Sdim  /// \brief Set type eliding, to skip outputting same types occurring in
462239462Sdim  /// template types.
463239462Sdim  void setElideType(bool Val = true) { ElideType = Val; }
464239462Sdim  bool getElideType() { return ElideType; }
465239462Sdim
466239462Sdim  /// \brief Set tree printing, to outputting the template difference in a
467239462Sdim  /// tree format.
468239462Sdim  void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; }
469239462Sdim  bool getPrintTemplateTree() { return PrintTemplateTree; }
470249423Sdim
471249423Sdim  /// \brief Warn when spellchecking is initated, for testing.
472249423Sdim  void setWarnOnSpellCheck(bool Val = false) { WarnOnSpellCheck = Val; }
473249423Sdim  bool getWarnOnSpellCheck() { return WarnOnSpellCheck; }
474239462Sdim
475239462Sdim  /// \brief Set color printing, so the type diffing will inject color markers
476239462Sdim  /// into the output.
477239462Sdim  void setShowColors(bool Val = false) { ShowColors = Val; }
478239462Sdim  bool getShowColors() { return ShowColors; }
479239462Sdim
480210299Sed  /// \brief Specify which overload candidates to show when overload resolution
481239462Sdim  /// fails.
482239462Sdim  ///
483239462Sdim  /// By default, we show all candidates.
484210299Sed  void setShowOverloads(OverloadsShown Val) {
485210299Sed    ShowOverloads = Val;
486210299Sed  }
487210299Sed  OverloadsShown getShowOverloads() const { return ShowOverloads; }
488210299Sed
489243830Sdim  /// \brief Pretend that the last diagnostic issued was ignored, so any
490243830Sdim  /// subsequent notes will be suppressed.
491239462Sdim  ///
492239462Sdim  /// This can be used by clients who suppress diagnostics themselves.
493198092Srdivacky  void setLastDiagnosticIgnored() {
494243830Sdim    if (LastDiagLevel == DiagnosticIDs::Fatal)
495243830Sdim      FatalErrorOccurred = true;
496218893Sdim    LastDiagLevel = DiagnosticIDs::Ignored;
497198092Srdivacky  }
498198092Srdivacky
499239462Sdim  /// \brief Controls whether otherwise-unmapped extension diagnostics are
500239462Sdim  /// mapped onto ignore/warning/error.
501239462Sdim  ///
502239462Sdim  /// This corresponds to the GCC -pedantic and -pedantic-errors option.
503193326Sed  void setExtensionHandlingBehavior(ExtensionHandling H) {
504193326Sed    ExtBehavior = H;
505193326Sed  }
506223017Sdim  ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; }
507198092Srdivacky
508239462Sdim  /// \brief Counter bumped when an __extension__  block is/ encountered.
509239462Sdim  ///
510239462Sdim  /// When non-zero, all extension diagnostics are entirely silenced, no
511239462Sdim  /// matter how they are mapped.
512193326Sed  void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
513193326Sed  void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
514198092Srdivacky  bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
515198092Srdivacky
516239462Sdim  /// \brief This allows the client to specify that certain warnings are
517239462Sdim  /// ignored.
518218893Sdim  ///
519239462Sdim  /// Notes can never be mapped, errors can only be mapped to fatal, and
520239462Sdim  /// WARNINGs and EXTENSIONs can be mapped arbitrarily.
521239462Sdim  ///
522218893Sdim  /// \param Loc The source location that this change of diagnostic state should
523218893Sdim  /// take affect. It can be null if we are setting the latest state.
524218893Sdim  void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
525218893Sdim                            SourceLocation Loc);
526198092Srdivacky
527239462Sdim  /// \brief Change an entire diagnostic group (e.g. "unknown-pragmas") to
528239462Sdim  /// have the specified mapping.
529218893Sdim  ///
530239462Sdim  /// \returns true (and ignores the request) if "Group" was unknown, false
531239462Sdim  /// otherwise.
532239462Sdim  ///
533239462Sdim  /// \param Loc The source location that this change of diagnostic state should
534218893Sdim  /// take affect. It can be null if we are setting the state from command-line.
535226633Sdim  bool setDiagnosticGroupMapping(StringRef Group, diag::Mapping Map,
536226633Sdim                                 SourceLocation Loc = SourceLocation());
537193326Sed
538239462Sdim  /// \brief Set the warning-as-error flag for the given diagnostic.
539239462Sdim  ///
540239462Sdim  /// This function always only operates on the current diagnostic state.
541234353Sdim  void setDiagnosticWarningAsError(diag::kind Diag, bool Enabled);
542234353Sdim
543239462Sdim  /// \brief Set the warning-as-error flag for the given diagnostic group.
544226633Sdim  ///
545239462Sdim  /// This function always only operates on the current diagnostic state.
546239462Sdim  ///
547226633Sdim  /// \returns True if the given group is unknown, false otherwise.
548226633Sdim  bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled);
549226633Sdim
550239462Sdim  /// \brief Set the error-as-fatal flag for the given diagnostic.
551239462Sdim  ///
552239462Sdim  /// This function always only operates on the current diagnostic state.
553234353Sdim  void setDiagnosticErrorAsFatal(diag::kind Diag, bool Enabled);
554234353Sdim
555239462Sdim  /// \brief Set the error-as-fatal flag for the given diagnostic group.
556226633Sdim  ///
557239462Sdim  /// This function always only operates on the current diagnostic state.
558239462Sdim  ///
559226633Sdim  /// \returns True if the given group is unknown, false otherwise.
560226633Sdim  bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);
561226633Sdim
562239462Sdim  /// \brief Add the specified mapping to all diagnostics.
563239462Sdim  ///
564239462Sdim  /// Mainly to be used by -Wno-everything to disable all warnings but allow
565239462Sdim  /// subsequent -W options to enable specific warnings.
566234353Sdim  void setMappingToAllDiagnostics(diag::Mapping Map,
567234353Sdim                                  SourceLocation Loc = SourceLocation());
568234353Sdim
569193326Sed  bool hasErrorOccurred() const { return ErrorOccurred; }
570249423Sdim
571249423Sdim  /// \brief Errors that actually prevent compilation, not those that are
572249423Sdim  /// upgraded from a warning by -Werror.
573249423Sdim  bool hasUncompilableErrorOccurred() const {
574249423Sdim    return UncompilableErrorOccurred;
575249423Sdim  }
576193326Sed  bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
577224145Sdim
578224145Sdim  /// \brief Determine whether any kind of unrecoverable error has occurred.
579224145Sdim  bool hasUnrecoverableErrorOccurred() const {
580224145Sdim    return FatalErrorOccurred || UnrecoverableErrorOccurred;
581224145Sdim  }
582224145Sdim
583207619Srdivacky  unsigned getNumWarnings() const { return NumWarnings; }
584198092Srdivacky
585212904Sdim  void setNumWarnings(unsigned NumWarnings) {
586212904Sdim    this->NumWarnings = NumWarnings;
587212904Sdim  }
588212904Sdim
589239462Sdim  /// \brief Return an ID for a diagnostic with the specified message and level.
590239462Sdim  ///
591249423Sdim  /// If this is the first request for this diagnostic, it is registered and
592239462Sdim  /// created, otherwise the existing ID is returned.
593226633Sdim  unsigned getCustomDiagID(Level L, StringRef Message) {
594218893Sdim    return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
595218893Sdim  }
596198092Srdivacky
597239462Sdim  /// \brief Converts a diagnostic argument (as an intptr_t) into the string
598239462Sdim  /// that represents it.
599193326Sed  void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
600193326Sed                          const char *Modifier, unsigned ModLen,
601193326Sed                          const char *Argument, unsigned ArgLen,
602198398Srdivacky                          const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
603226633Sdim                          SmallVectorImpl<char> &Output,
604243830Sdim                          ArrayRef<intptr_t> QualTypeVals) const {
605198398Srdivacky    ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
606224145Sdim                  PrevArgs, NumPrevArgs, Output, ArgToStringCookie,
607224145Sdim                  QualTypeVals);
608193326Sed  }
609198092Srdivacky
610193326Sed  void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
611193326Sed    ArgToStringFn = Fn;
612193326Sed    ArgToStringCookie = Cookie;
613193326Sed  }
614198092Srdivacky
615249423Sdim  /// \brief Note that the prior diagnostic was emitted by some other
616249423Sdim  /// \c DiagnosticsEngine, and we may be attaching a note to that diagnostic.
617249423Sdim  void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) {
618249423Sdim    LastDiagLevel = Other.LastDiagLevel;
619249423Sdim  }
620249423Sdim
621212904Sdim  /// \brief Reset the state of the diagnostic object to its initial
622212904Sdim  /// configuration.
623212904Sdim  void Reset();
624212904Sdim
625193326Sed  //===--------------------------------------------------------------------===//
626226633Sdim  // DiagnosticsEngine classification and reporting interfaces.
627193326Sed  //
628193326Sed
629226633Sdim  /// \brief Based on the way the client configured the DiagnosticsEngine
630218893Sdim  /// object, classify the specified diagnostic ID into a Level, consumable by
631226633Sdim  /// the DiagnosticConsumer.
632193326Sed  ///
633218893Sdim  /// \param Loc The source location we are interested in finding out the
634218893Sdim  /// diagnostic state. Can be null in order to query the latest state.
635226633Sdim  Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
636226633Sdim    return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
637207619Srdivacky  }
638198092Srdivacky
639239462Sdim  /// \brief Issue the message to the client.
640239462Sdim  ///
641239462Sdim  /// This actually returns an instance of DiagnosticBuilder which emits the
642239462Sdim  /// diagnostics (through @c ProcessDiag) when it is destroyed.
643239462Sdim  ///
644239462Sdim  /// \param DiagID A member of the @c diag::kind enum.
645239462Sdim  /// \param Loc Represents the source location associated with the diagnostic,
646193326Sed  /// which can be an invalid location if no position information is available.
647239462Sdim  inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID);
648199482Srdivacky  inline DiagnosticBuilder Report(unsigned DiagID);
649193326Sed
650223017Sdim  void Report(const StoredDiagnostic &storedDiag);
651223017Sdim
652206084Srdivacky  /// \brief Determine whethere there is already a diagnostic in flight.
653206084Srdivacky  bool isDiagnosticInFlight() const { return CurDiagID != ~0U; }
654206084Srdivacky
655206084Srdivacky  /// \brief Set the "delayed" diagnostic that will be emitted once
656206084Srdivacky  /// the current diagnostic completes.
657206084Srdivacky  ///
658206084Srdivacky  ///  If a diagnostic is already in-flight but the front end must
659206084Srdivacky  ///  report a problem (e.g., with an inconsistent file system
660206084Srdivacky  ///  state), this routine sets a "delayed" diagnostic that will be
661206084Srdivacky  ///  emitted after the current diagnostic completes. This should
662206084Srdivacky  ///  only be used for fatal errors detected at inconvenient
663206084Srdivacky  ///  times. If emitting a delayed diagnostic causes a second delayed
664206084Srdivacky  ///  diagnostic to be introduced, that second delayed diagnostic
665206084Srdivacky  ///  will be ignored.
666206084Srdivacky  ///
667206084Srdivacky  /// \param DiagID The ID of the diagnostic being delayed.
668206084Srdivacky  ///
669206084Srdivacky  /// \param Arg1 A string argument that will be provided to the
670206084Srdivacky  /// diagnostic. A copy of this string will be stored in the
671226633Sdim  /// DiagnosticsEngine object itself.
672206084Srdivacky  ///
673206084Srdivacky  /// \param Arg2 A string argument that will be provided to the
674206084Srdivacky  /// diagnostic. A copy of this string will be stored in the
675226633Sdim  /// DiagnosticsEngine object itself.
676226633Sdim  void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
677226633Sdim                            StringRef Arg2 = "");
678206084Srdivacky
679193326Sed  /// \brief Clear out the current diagnostic.
680193326Sed  void Clear() { CurDiagID = ~0U; }
681198092Srdivacky
682193326Sedprivate:
683206084Srdivacky  /// \brief Report the delayed diagnostic.
684206084Srdivacky  void ReportDelayed();
685206084Srdivacky
686193326Sed  // This is private state used by DiagnosticBuilder.  We put it here instead of
687193326Sed  // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
688193326Sed  // object.  This implementation choice means that we can only have one
689193326Sed  // diagnostic "in flight" at a time, but this seems to be a reasonable
690193326Sed  // tradeoff to keep these objects small.  Assertions verify that only one
691193326Sed  // diagnostic is in flight at a time.
692218893Sdim  friend class DiagnosticIDs;
693193326Sed  friend class DiagnosticBuilder;
694226633Sdim  friend class Diagnostic;
695218893Sdim  friend class PartialDiagnostic;
696218893Sdim  friend class DiagnosticErrorTrap;
697218893Sdim
698239462Sdim  /// \brief The location of the current diagnostic that is in flight.
699218893Sdim  SourceLocation CurDiagLoc;
700198092Srdivacky
701239462Sdim  /// \brief The ID of the current diagnostic that is in flight.
702239462Sdim  ///
703193326Sed  /// This is set to ~0U when there is no diagnostic in flight.
704193326Sed  unsigned CurDiagID;
705193326Sed
706193326Sed  enum {
707239462Sdim    /// \brief The maximum number of arguments we can hold.
708239462Sdim    ///
709239462Sdim    /// We currently only support up to 10 arguments (%0-%9).  A single
710239462Sdim    /// diagnostic with more than that almost certainly has to be simplified
711239462Sdim    /// anyway.
712234353Sdim    MaxArguments = 10,
713234353Sdim
714239462Sdim    /// \brief The maximum number of ranges we can hold.
715234353Sdim    MaxRanges = 10,
716234353Sdim
717239462Sdim    /// \brief The maximum number of ranges we can hold.
718234353Sdim    MaxFixItHints = 10
719193326Sed  };
720198092Srdivacky
721239462Sdim  /// \brief The number of entries in Arguments.
722193326Sed  signed char NumDiagArgs;
723239462Sdim  /// \brief The number of ranges in the DiagRanges array.
724193326Sed  unsigned char NumDiagRanges;
725239462Sdim  /// \brief The number of hints in the DiagFixItHints array.
726234353Sdim  unsigned char NumDiagFixItHints;
727193326Sed
728239462Sdim  /// \brief Specifies whether an argument is in DiagArgumentsStr or
729239462Sdim  /// in DiagArguments.
730239462Sdim  ///
731239462Sdim  /// This is an array of ArgumentKind::ArgumentKind enum values, one for each
732239462Sdim  /// argument.
733193326Sed  unsigned char DiagArgumentsKind[MaxArguments];
734198092Srdivacky
735239462Sdim  /// \brief Holds the values of each string argument for the current
736239462Sdim  /// diagnostic.
737239462Sdim  ///
738239462Sdim  /// This is only used when the corresponding ArgumentKind is ak_std_string.
739193326Sed  std::string DiagArgumentsStr[MaxArguments];
740193326Sed
741239462Sdim  /// \brief The values for the various substitution positions.
742239462Sdim  ///
743239462Sdim  /// This is used when the argument is not an std::string.  The specific
744239462Sdim  /// value is mangled into an intptr_t and the interpretation depends on
745239462Sdim  /// exactly what sort of argument kind it is.
746193326Sed  intptr_t DiagArgumentsVal[MaxArguments];
747198092Srdivacky
748239462Sdim  /// \brief The list of ranges added to this diagnostic.
749234353Sdim  CharSourceRange DiagRanges[MaxRanges];
750198092Srdivacky
751239462Sdim  /// \brief If valid, provides a hint with some code to insert, remove,
752234353Sdim  /// or modify at a particular position.
753234353Sdim  FixItHint DiagFixItHints[MaxFixItHints];
754193326Sed
755234353Sdim  DiagnosticMappingInfo makeMappingInfo(diag::Mapping Map, SourceLocation L) {
756234353Sdim    bool isPragma = L.isValid();
757234353Sdim    DiagnosticMappingInfo MappingInfo = DiagnosticMappingInfo::Make(
758234353Sdim      Map, /*IsUser=*/true, isPragma);
759193326Sed
760234353Sdim    // If this is a pragma mapping, then set the diagnostic mapping flags so
761234353Sdim    // that we override command line options.
762234353Sdim    if (isPragma) {
763234353Sdim      MappingInfo.setNoWarningAsError(true);
764234353Sdim      MappingInfo.setNoErrorAsFatal(true);
765234353Sdim    }
766234353Sdim
767234353Sdim    return MappingInfo;
768234353Sdim  }
769234353Sdim
770239462Sdim  /// \brief Used to report a diagnostic that is finally fully formed.
771194179Sed  ///
772239462Sdim  /// \returns true if the diagnostic was emitted, false if it was suppressed.
773218893Sdim  bool ProcessDiag() {
774218893Sdim    return Diags->ProcessDiag(*this);
775218893Sdim  }
776218893Sdim
777234353Sdim  /// @name Diagnostic Emission
778234353Sdim  /// @{
779234353Sdimprotected:
780234353Sdim  // Sema requires access to the following functions because the current design
781234353Sdim  // of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to
782234353Sdim  // access us directly to ensure we minimize the emitted code for the common
783234353Sdim  // Sema::Diag() patterns.
784234353Sdim  friend class Sema;
785234353Sdim
786234353Sdim  /// \brief Emit the current diagnostic and clear the diagnostic state.
787239462Sdim  ///
788239462Sdim  /// \param Force Emit the diagnostic regardless of suppression settings.
789239462Sdim  bool EmitCurrentDiagnostic(bool Force = false);
790234353Sdim
791234353Sdim  unsigned getCurrentDiagID() const { return CurDiagID; }
792234353Sdim
793234353Sdim  SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; }
794234353Sdim
795234353Sdim  /// @}
796234353Sdim
797218893Sdim  friend class ASTReader;
798218893Sdim  friend class ASTWriter;
799193326Sed};
800193326Sed
801218893Sdim/// \brief RAII class that determines when any errors have occurred
802218893Sdim/// between the time the instance was created and the time it was
803218893Sdim/// queried.
804218893Sdimclass DiagnosticErrorTrap {
805226633Sdim  DiagnosticsEngine &Diag;
806226633Sdim  unsigned NumErrors;
807226633Sdim  unsigned NumUnrecoverableErrors;
808218893Sdim
809218893Sdimpublic:
810226633Sdim  explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag)
811224145Sdim    : Diag(Diag) { reset(); }
812218893Sdim
813218893Sdim  /// \brief Determine whether any errors have occurred since this
814218893Sdim  /// object instance was created.
815218893Sdim  bool hasErrorOccurred() const {
816226633Sdim    return Diag.TrapNumErrorsOccurred > NumErrors;
817218893Sdim  }
818218893Sdim
819224145Sdim  /// \brief Determine whether any unrecoverable errors have occurred since this
820224145Sdim  /// object instance was created.
821224145Sdim  bool hasUnrecoverableErrorOccurred() const {
822226633Sdim    return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
823224145Sdim  }
824224145Sdim
825239462Sdim  /// \brief Set to initial state of "no errors occurred".
826224145Sdim  void reset() {
827226633Sdim    NumErrors = Diag.TrapNumErrorsOccurred;
828226633Sdim    NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
829224145Sdim  }
830218893Sdim};
831218893Sdim
832193326Sed//===----------------------------------------------------------------------===//
833193326Sed// DiagnosticBuilder
834193326Sed//===----------------------------------------------------------------------===//
835193326Sed
836239462Sdim/// \brief A little helper class used to produce diagnostics.
837193326Sed///
838239462Sdim/// This is constructed by the DiagnosticsEngine::Report method, and
839239462Sdim/// allows insertion of extra information (arguments and source ranges) into
840239462Sdim/// the currently "in flight" diagnostic.  When the temporary for the builder
841239462Sdim/// is destroyed, the diagnostic is issued.
842239462Sdim///
843193326Sed/// Note that many of these will be created as temporary objects (many call
844193326Sed/// sites), so we want them to be small and we never want their address taken.
845193326Sed/// This ensures that compilers with somewhat reasonable optimizers will promote
846193326Sed/// the common fields to registers, eliminating increments of the NumArgs field,
847193326Sed/// for example.
848193326Sedclass DiagnosticBuilder {
849226633Sdim  mutable DiagnosticsEngine *DiagObj;
850234353Sdim  mutable unsigned NumArgs, NumRanges, NumFixits;
851198092Srdivacky
852234353Sdim  /// \brief Status variable indicating if this diagnostic is still active.
853234353Sdim  ///
854234353Sdim  // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)),
855234353Sdim  // but LLVM is not currently smart enough to eliminate the null check that
856234353Sdim  // Emit() would end up with if we used that as our status variable.
857234353Sdim  mutable bool IsActive;
858234353Sdim
859239462Sdim  /// \brief Flag indicating that this diagnostic is being emitted via a
860239462Sdim  /// call to ForceEmit.
861239462Sdim  mutable bool IsForceEmit;
862239462Sdim
863243830Sdim  void operator=(const DiagnosticBuilder &) LLVM_DELETED_FUNCTION;
864226633Sdim  friend class DiagnosticsEngine;
865239462Sdim
866239462Sdim  DiagnosticBuilder()
867239462Sdim    : DiagObj(0), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(false),
868239462Sdim      IsForceEmit(false) { }
869239462Sdim
870226633Sdim  explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
871239462Sdim    : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true),
872239462Sdim      IsForceEmit(false) {
873234353Sdim    assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!");
874234353Sdim  }
875193326Sed
876218893Sdim  friend class PartialDiagnostic;
877239462Sdim
878218893Sdimprotected:
879234353Sdim  void FlushCounts() {
880234353Sdim    DiagObj->NumDiagArgs = NumArgs;
881234353Sdim    DiagObj->NumDiagRanges = NumRanges;
882234353Sdim    DiagObj->NumDiagFixItHints = NumFixits;
883193326Sed  }
884193326Sed
885234353Sdim  /// \brief Clear out the current diagnostic.
886234353Sdim  void Clear() const {
887234353Sdim    DiagObj = 0;
888234353Sdim    IsActive = false;
889239462Sdim    IsForceEmit = false;
890234353Sdim  }
891194179Sed
892239462Sdim  /// \brief Determine whether this diagnostic is still active.
893234353Sdim  bool isActive() const { return IsActive; }
894194179Sed
895193326Sed  /// \brief Force the diagnostic builder to emit the diagnostic now.
896193326Sed  ///
897193326Sed  /// Once this function has been called, the DiagnosticBuilder object
898193326Sed  /// should not be used again before it is destroyed.
899194179Sed  ///
900194179Sed  /// \returns true if a diagnostic was emitted, false if the
901194179Sed  /// diagnostic was suppressed.
902234353Sdim  bool Emit() {
903234353Sdim    // If this diagnostic is inactive, then its soul was stolen by the copy ctor
904234353Sdim    // (or by a subclass, as in SemaDiagnosticBuilder).
905234353Sdim    if (!isActive()) return false;
906193326Sed
907234353Sdim    // When emitting diagnostics, we set the final argument count into
908234353Sdim    // the DiagnosticsEngine object.
909234353Sdim    FlushCounts();
910198092Srdivacky
911234353Sdim    // Process the diagnostic.
912239462Sdim    bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit);
913203955Srdivacky
914234353Sdim    // This diagnostic is dead.
915234353Sdim    Clear();
916234353Sdim
917234353Sdim    return Result;
918218893Sdim  }
919218893Sdim
920234353Sdimpublic:
921234353Sdim  /// Copy constructor.  When copied, this "takes" the diagnostic info from the
922234353Sdim  /// input and neuters it.
923234353Sdim  DiagnosticBuilder(const DiagnosticBuilder &D) {
924234353Sdim    DiagObj = D.DiagObj;
925234353Sdim    IsActive = D.IsActive;
926239462Sdim    IsForceEmit = D.IsForceEmit;
927234353Sdim    D.Clear();
928234353Sdim    NumArgs = D.NumArgs;
929234353Sdim    NumRanges = D.NumRanges;
930234353Sdim    NumFixits = D.NumFixits;
931234353Sdim  }
932234353Sdim
933239462Sdim  /// \brief Retrieve an empty diagnostic builder.
934239462Sdim  static DiagnosticBuilder getEmpty() {
935239462Sdim    return DiagnosticBuilder();
936239462Sdim  }
937239462Sdim
938239462Sdim  /// \brief Emits the diagnostic.
939234353Sdim  ~DiagnosticBuilder() {
940234353Sdim    Emit();
941234353Sdim  }
942218893Sdim
943239462Sdim  /// \brief Forces the diagnostic to be emitted.
944239462Sdim  const DiagnosticBuilder &setForceEmit() const {
945239462Sdim    IsForceEmit = true;
946239462Sdim    return *this;
947239462Sdim  }
948239462Sdim
949239462Sdim  /// \brief Conversion of DiagnosticBuilder to bool always returns \c true.
950239462Sdim  ///
951239462Sdim  /// This allows is to be used in boolean error contexts (where \c true is
952239462Sdim  /// used to indicate that an error has occurred), like:
953239462Sdim  /// \code
954193326Sed  /// return Diag(...);
955239462Sdim  /// \endcode
956193326Sed  operator bool() const { return true; }
957193326Sed
958226633Sdim  void AddString(StringRef S) const {
959234353Sdim    assert(isActive() && "Clients must not add to cleared diagnostic!");
960226633Sdim    assert(NumArgs < DiagnosticsEngine::MaxArguments &&
961193326Sed           "Too many arguments to diagnostic!");
962234353Sdim    DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string;
963234353Sdim    DiagObj->DiagArgumentsStr[NumArgs++] = S;
964193326Sed  }
965198092Srdivacky
966226633Sdim  void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
967234353Sdim    assert(isActive() && "Clients must not add to cleared diagnostic!");
968226633Sdim    assert(NumArgs < DiagnosticsEngine::MaxArguments &&
969193326Sed           "Too many arguments to diagnostic!");
970234353Sdim    DiagObj->DiagArgumentsKind[NumArgs] = Kind;
971234353Sdim    DiagObj->DiagArgumentsVal[NumArgs++] = V;
972193326Sed  }
973198092Srdivacky
974210299Sed  void AddSourceRange(const CharSourceRange &R) const {
975234353Sdim    assert(isActive() && "Clients must not add to cleared diagnostic!");
976234353Sdim    assert(NumRanges < DiagnosticsEngine::MaxRanges &&
977193326Sed           "Too many arguments to diagnostic!");
978234353Sdim    DiagObj->DiagRanges[NumRanges++] = R;
979198092Srdivacky  }
980193326Sed
981206084Srdivacky  void AddFixItHint(const FixItHint &Hint) const {
982234353Sdim    assert(isActive() && "Clients must not add to cleared diagnostic!");
983234353Sdim    assert(NumFixits < DiagnosticsEngine::MaxFixItHints &&
984234353Sdim           "Too many arguments to diagnostic!");
985234353Sdim    DiagObj->DiagFixItHints[NumFixits++] = Hint;
986193326Sed  }
987243830Sdim
988243830Sdim  bool hasMaxRanges() const {
989243830Sdim    return NumRanges == DiagnosticsEngine::MaxRanges;
990243830Sdim  }
991193326Sed};
992193326Sed
993193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
994226633Sdim                                           StringRef S) {
995193326Sed  DB.AddString(S);
996193326Sed  return DB;
997193326Sed}
998193326Sed
999193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1000193326Sed                                           const char *Str) {
1001193326Sed  DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
1002226633Sdim                  DiagnosticsEngine::ak_c_string);
1003193326Sed  return DB;
1004193326Sed}
1005193326Sed
1006193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
1007226633Sdim  DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
1008193326Sed  return DB;
1009193326Sed}
1010193326Sed
1011193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
1012226633Sdim  DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
1013193326Sed  return DB;
1014193326Sed}
1015193326Sed
1016193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1017193326Sed                                           unsigned I) {
1018226633Sdim  DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
1019193326Sed  return DB;
1020193326Sed}
1021193326Sed
1022193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1023193326Sed                                           const IdentifierInfo *II) {
1024193326Sed  DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
1025226633Sdim                  DiagnosticsEngine::ak_identifierinfo);
1026193326Sed  return DB;
1027193326Sed}
1028198092Srdivacky
1029198092Srdivacky// Adds a DeclContext to the diagnostic. The enable_if template magic is here
1030198092Srdivacky// so that we only match those arguments that are (statically) DeclContexts;
1031198092Srdivacky// other arguments that derive from DeclContext (e.g., RecordDecls) will not
1032198092Srdivacky// match.
1033198092Srdivackytemplate<typename T>
1034198092Srdivackyinline
1035198092Srdivackytypename llvm::enable_if<llvm::is_same<T, DeclContext>,
1036198092Srdivacky                         const DiagnosticBuilder &>::type
1037198092Srdivackyoperator<<(const DiagnosticBuilder &DB, T *DC) {
1038198092Srdivacky  DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
1039226633Sdim                  DiagnosticsEngine::ak_declcontext);
1040198092Srdivacky  return DB;
1041198092Srdivacky}
1042193326Sed
1043193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1044193326Sed                                           const SourceRange &R) {
1045210299Sed  DB.AddSourceRange(CharSourceRange::getTokenRange(R));
1046193326Sed  return DB;
1047193326Sed}
1048193326Sed
1049193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1050210299Sed                                           const CharSourceRange &R) {
1051210299Sed  DB.AddSourceRange(R);
1052210299Sed  return DB;
1053210299Sed}
1054210299Sed
1055210299Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1056206084Srdivacky                                           const FixItHint &Hint) {
1057234353Sdim  if (!Hint.isNull())
1058234353Sdim    DB.AddFixItHint(Hint);
1059193326Sed  return DB;
1060193326Sed}
1061193326Sed
1062226633Sdiminline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
1063218893Sdim                                            unsigned DiagID){
1064193326Sed  assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
1065193326Sed  CurDiagLoc = Loc;
1066193326Sed  CurDiagID = DiagID;
1067193326Sed  return DiagnosticBuilder(this);
1068193326Sed}
1069226633Sdiminline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
1070218893Sdim  return Report(SourceLocation(), DiagID);
1071199482Srdivacky}
1072193326Sed
1073193326Sed//===----------------------------------------------------------------------===//
1074226633Sdim// Diagnostic
1075193326Sed//===----------------------------------------------------------------------===//
1076198092Srdivacky
1077239462Sdim/// A little helper class (which is basically a smart pointer that forwards
1078239462Sdim/// info from DiagnosticsEngine) that allows clients to enquire about the
1079239462Sdim/// currently in-flight diagnostic.
1080226633Sdimclass Diagnostic {
1081226633Sdim  const DiagnosticsEngine *DiagObj;
1082226633Sdim  StringRef StoredDiagMessage;
1083193326Sedpublic:
1084226633Sdim  explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {}
1085226633Sdim  Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage)
1086223017Sdim    : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
1087198092Srdivacky
1088226633Sdim  const DiagnosticsEngine *getDiags() const { return DiagObj; }
1089193326Sed  unsigned getID() const { return DiagObj->CurDiagID; }
1090218893Sdim  const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
1091218893Sdim  bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
1092218893Sdim  SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}
1093198092Srdivacky
1094193326Sed  unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
1095198092Srdivacky
1096239462Sdim  /// \brief Return the kind of the specified index.
1097239462Sdim  ///
1098239462Sdim  /// Based on the kind of argument, the accessors below can be used to get
1099239462Sdim  /// the value.
1100239462Sdim  ///
1101239462Sdim  /// \pre Idx < getNumArgs()
1102226633Sdim  DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const {
1103193326Sed    assert(Idx < getNumArgs() && "Argument index out of range!");
1104226633Sdim    return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
1105193326Sed  }
1106198092Srdivacky
1107239462Sdim  /// \brief Return the provided argument string specified by \p Idx.
1108239462Sdim  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string
1109193326Sed  const std::string &getArgStdStr(unsigned Idx) const {
1110226633Sdim    assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
1111193326Sed           "invalid argument accessor!");
1112193326Sed    return DiagObj->DiagArgumentsStr[Idx];
1113193326Sed  }
1114198092Srdivacky
1115239462Sdim  /// \brief Return the specified C string argument.
1116239462Sdim  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string
1117193326Sed  const char *getArgCStr(unsigned Idx) const {
1118226633Sdim    assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
1119193326Sed           "invalid argument accessor!");
1120193326Sed    return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
1121193326Sed  }
1122198092Srdivacky
1123239462Sdim  /// \brief Return the specified signed integer argument.
1124239462Sdim  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint
1125193326Sed  int getArgSInt(unsigned Idx) const {
1126226633Sdim    assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
1127193326Sed           "invalid argument accessor!");
1128193326Sed    return (int)DiagObj->DiagArgumentsVal[Idx];
1129193326Sed  }
1130198092Srdivacky
1131239462Sdim  /// \brief Return the specified unsigned integer argument.
1132239462Sdim  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint
1133193326Sed  unsigned getArgUInt(unsigned Idx) const {
1134226633Sdim    assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
1135193326Sed           "invalid argument accessor!");
1136193326Sed    return (unsigned)DiagObj->DiagArgumentsVal[Idx];
1137193326Sed  }
1138198092Srdivacky
1139239462Sdim  /// \brief Return the specified IdentifierInfo argument.
1140239462Sdim  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo
1141193326Sed  const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
1142226633Sdim    assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
1143193326Sed           "invalid argument accessor!");
1144193326Sed    return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
1145193326Sed  }
1146198092Srdivacky
1147239462Sdim  /// \brief Return the specified non-string argument in an opaque form.
1148239462Sdim  /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string
1149193326Sed  intptr_t getRawArg(unsigned Idx) const {
1150226633Sdim    assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
1151193326Sed           "invalid argument accessor!");
1152193326Sed    return DiagObj->DiagArgumentsVal[Idx];
1153193326Sed  }
1154198092Srdivacky
1155239462Sdim  /// \brief Return the number of source ranges associated with this diagnostic.
1156193326Sed  unsigned getNumRanges() const {
1157193326Sed    return DiagObj->NumDiagRanges;
1158193326Sed  }
1159198092Srdivacky
1160239462Sdim  /// \pre Idx < getNumRanges()
1161210299Sed  const CharSourceRange &getRange(unsigned Idx) const {
1162193326Sed    assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
1163203955Srdivacky    return DiagObj->DiagRanges[Idx];
1164193326Sed  }
1165198092Srdivacky
1166234353Sdim  /// \brief Return an array reference for this diagnostic's ranges.
1167234353Sdim  ArrayRef<CharSourceRange> getRanges() const {
1168234353Sdim    return llvm::makeArrayRef(DiagObj->DiagRanges, DiagObj->NumDiagRanges);
1169234353Sdim  }
1170234353Sdim
1171206084Srdivacky  unsigned getNumFixItHints() const {
1172234353Sdim    return DiagObj->NumDiagFixItHints;
1173193326Sed  }
1174193326Sed
1175206084Srdivacky  const FixItHint &getFixItHint(unsigned Idx) const {
1176234353Sdim    assert(Idx < getNumFixItHints() && "Invalid index!");
1177234353Sdim    return DiagObj->DiagFixItHints[Idx];
1178193326Sed  }
1179193326Sed
1180206084Srdivacky  const FixItHint *getFixItHints() const {
1181234353Sdim    return getNumFixItHints()? DiagObj->DiagFixItHints : 0;
1182193326Sed  }
1183193326Sed
1184239462Sdim  /// \brief Format this diagnostic into a string, substituting the
1185239462Sdim  /// formal arguments into the %0 slots.
1186239462Sdim  ///
1187239462Sdim  /// The result is appended onto the \p OutStr array.
1188226633Sdim  void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;
1189202379Srdivacky
1190239462Sdim  /// \brief Format the given format-string into the output buffer using the
1191239462Sdim  /// arguments stored in this diagnostic.
1192202379Srdivacky  void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
1193226633Sdim                        SmallVectorImpl<char> &OutStr) const;
1194204643Srdivacky};
1195203955Srdivacky
1196204643Srdivacky/**
1197218893Sdim * \brief Represents a diagnostic in a form that can be retained until its
1198218893Sdim * corresponding source manager is destroyed.
1199204643Srdivacky */
1200204643Srdivackyclass StoredDiagnostic {
1201218893Sdim  unsigned ID;
1202226633Sdim  DiagnosticsEngine::Level Level;
1203204643Srdivacky  FullSourceLoc Loc;
1204204643Srdivacky  std::string Message;
1205210299Sed  std::vector<CharSourceRange> Ranges;
1206206084Srdivacky  std::vector<FixItHint> FixIts;
1207204643Srdivacky
1208204643Srdivackypublic:
1209204643Srdivacky  StoredDiagnostic();
1210226633Sdim  StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
1211226633Sdim  StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1212226633Sdim                   StringRef Message);
1213226633Sdim  StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1214226633Sdim                   StringRef Message, FullSourceLoc Loc,
1215226633Sdim                   ArrayRef<CharSourceRange> Ranges,
1216226633Sdim                   ArrayRef<FixItHint> Fixits);
1217204643Srdivacky  ~StoredDiagnostic();
1218204643Srdivacky
1219204643Srdivacky  /// \brief Evaluates true when this object stores a diagnostic.
1220204643Srdivacky  operator bool() const { return Message.size() > 0; }
1221204643Srdivacky
1222218893Sdim  unsigned getID() const { return ID; }
1223226633Sdim  DiagnosticsEngine::Level getLevel() const { return Level; }
1224204643Srdivacky  const FullSourceLoc &getLocation() const { return Loc; }
1225226633Sdim  StringRef getMessage() const { return Message; }
1226212904Sdim
1227212904Sdim  void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
1228212904Sdim
1229210299Sed  typedef std::vector<CharSourceRange>::const_iterator range_iterator;
1230204643Srdivacky  range_iterator range_begin() const { return Ranges.begin(); }
1231204643Srdivacky  range_iterator range_end() const { return Ranges.end(); }
1232204643Srdivacky  unsigned range_size() const { return Ranges.size(); }
1233234353Sdim
1234234353Sdim  ArrayRef<CharSourceRange> getRanges() const {
1235234353Sdim    return llvm::makeArrayRef(Ranges);
1236234353Sdim  }
1237204643Srdivacky
1238234353Sdim
1239206084Srdivacky  typedef std::vector<FixItHint>::const_iterator fixit_iterator;
1240204643Srdivacky  fixit_iterator fixit_begin() const { return FixIts.begin(); }
1241204643Srdivacky  fixit_iterator fixit_end() const { return FixIts.end(); }
1242204643Srdivacky  unsigned fixit_size() const { return FixIts.size(); }
1243234353Sdim
1244234353Sdim  ArrayRef<FixItHint> getFixIts() const {
1245234353Sdim    return llvm::makeArrayRef(FixIts);
1246234353Sdim  }
1247193326Sed};
1248198092Srdivacky
1249239462Sdim/// \brief Abstract interface, implemented by clients of the front-end, which
1250239462Sdim/// formats and prints fully processed diagnostics.
1251226633Sdimclass DiagnosticConsumer {
1252218893Sdimprotected:
1253239462Sdim  unsigned NumWarnings;       ///< Number of warnings reported
1254239462Sdim  unsigned NumErrors;         ///< Number of errors reported
1255218893Sdim
1256193326Sedpublic:
1257226633Sdim  DiagnosticConsumer() : NumWarnings(0), NumErrors(0) { }
1258218893Sdim
1259218893Sdim  unsigned getNumErrors() const { return NumErrors; }
1260218893Sdim  unsigned getNumWarnings() const { return NumWarnings; }
1261234353Sdim  virtual void clear() { NumWarnings = NumErrors = 0; }
1262218893Sdim
1263226633Sdim  virtual ~DiagnosticConsumer();
1264198092Srdivacky
1265239462Sdim  /// \brief Callback to inform the diagnostic client that processing
1266198954Srdivacky  /// of a source file is beginning.
1267198954Srdivacky  ///
1268198954Srdivacky  /// Note that diagnostics may be emitted outside the processing of a source
1269198954Srdivacky  /// file, for example during the parsing of command line options. However,
1270198954Srdivacky  /// diagnostics with source range information are required to only be emitted
1271198954Srdivacky  /// in between BeginSourceFile() and EndSourceFile().
1272198954Srdivacky  ///
1273239462Sdim  /// \param LangOpts The language options for the source file being processed.
1274239462Sdim  /// \param PP The preprocessor object being used for the source; this is
1275239462Sdim  /// optional, e.g., it may not be present when processing AST source files.
1276199482Srdivacky  virtual void BeginSourceFile(const LangOptions &LangOpts,
1277199482Srdivacky                               const Preprocessor *PP = 0) {}
1278198092Srdivacky
1279239462Sdim  /// \brief Callback to inform the diagnostic client that processing
1280239462Sdim  /// of a source file has ended.
1281239462Sdim  ///
1282239462Sdim  /// The diagnostic client should assume that any objects made available via
1283239462Sdim  /// BeginSourceFile() are inaccessible.
1284198954Srdivacky  virtual void EndSourceFile() {}
1285198954Srdivacky
1286234353Sdim  /// \brief Callback to inform the diagnostic client that processing of all
1287234353Sdim  /// source files has ended.
1288234353Sdim  virtual void finish() {}
1289234353Sdim
1290239462Sdim  /// \brief Indicates whether the diagnostics handled by this
1291226633Sdim  /// DiagnosticConsumer should be included in the number of diagnostics
1292226633Sdim  /// reported by DiagnosticsEngine.
1293239462Sdim  ///
1294239462Sdim  /// The default implementation returns true.
1295193326Sed  virtual bool IncludeInDiagnosticCounts() const;
1296193326Sed
1297239462Sdim  /// \brief Handle this diagnostic, reporting it to the user or
1298193326Sed  /// capturing it to a log as needed.
1299218893Sdim  ///
1300239462Sdim  /// The default implementation just keeps track of the total number of
1301239462Sdim  /// warnings and errors.
1302226633Sdim  virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1303226633Sdim                                const Diagnostic &Info);
1304226633Sdim
1305226633Sdim  /// \brief Clone the diagnostic consumer, producing an equivalent consumer
1306226633Sdim  /// that can be used in a different context.
1307226633Sdim  virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const = 0;
1308193326Sed};
1309193326Sed
1310239462Sdim/// \brief A diagnostic client that ignores all diagnostics.
1311226633Sdimclass IgnoringDiagConsumer : public DiagnosticConsumer {
1312234353Sdim  virtual void anchor();
1313226633Sdim  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1314226633Sdim                        const Diagnostic &Info) {
1315226633Sdim    // Just ignore it.
1316226633Sdim  }
1317226633Sdim  DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
1318226633Sdim    return new IgnoringDiagConsumer();
1319226633Sdim  }
1320226633Sdim};
1321226633Sdim
1322239462Sdim// Struct used for sending info about how a type should be printed.
1323239462Sdimstruct TemplateDiffTypes {
1324239462Sdim  intptr_t FromType;
1325239462Sdim  intptr_t ToType;
1326239462Sdim  unsigned PrintTree : 1;
1327239462Sdim  unsigned PrintFromType : 1;
1328239462Sdim  unsigned ElideType : 1;
1329239462Sdim  unsigned ShowColors : 1;
1330239462Sdim  // The printer sets this variable to true if the template diff was used.
1331239462Sdim  unsigned TemplateDiffUsed : 1;
1332239462Sdim};
1333239462Sdim
1334239462Sdim/// Special character that the diagnostic printer will use to toggle the bold
1335239462Sdim/// attribute.  The character itself will be not be printed.
1336239462Sdimconst char ToggleHighlight = 127;
1337239462Sdim
1338193326Sed}  // end namespace clang
1339193326Sed
1340193326Sed#endif
1341