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"
24198092Srdivacky#include "llvm/Support/type_traits.h"
25249423Sdim#include <list>
26198092Srdivacky#include <vector>
27193326Sed
28193326Sednamespace clang {
29226633Sdim  class DiagnosticConsumer;
30198092Srdivacky  class DiagnosticBuilder;
31243830Sdim  class DiagnosticOptions;
32193326Sed  class IdentifierInfo;
33218893Sdim  class DeclContext;
34193326Sed  class LangOptions;
35199482Srdivacky  class Preprocessor;
36218893Sdim  class DiagnosticErrorTrap;
37223017Sdim  class StoredDiagnostic;
38198092Srdivacky
39193326Sed/// \brief Annotates a diagnostic with some code that should be
40193326Sed/// inserted, removed, or replaced to fix the problem.
41193326Sed///
42193326Sed/// This kind of hint should be used when we are certain that the
43193326Sed/// introduction, removal, or modification of a particular (small!)
44193326Sed/// amount of code will correct a compilation error. The compiler
45193326Sed/// should also provide full recovery from such errors, such that
46193326Sed/// suppressing the diagnostic output can still result in successful
47193326Sed/// compilation.
48206084Srdivackyclass FixItHint {
49193326Sedpublic:
50212904Sdim  /// \brief Code that should be replaced to correct the error. Empty for an
51212904Sdim  /// insertion hint.
52210299Sed  CharSourceRange RemoveRange;
53193326Sed
54234353Sdim  /// \brief Code in the specific range that should be inserted in the insertion
55234353Sdim  /// location.
56234353Sdim  CharSourceRange InsertFromRange;
57234353Sdim
58193326Sed  /// \brief The actual code to insert at the insertion location, as a
59193326Sed  /// string.
60193326Sed  std::string CodeToInsert;
61193326Sed
62234353Sdim  bool BeforePreviousInsertions;
63234353Sdim
64193326Sed  /// \brief Empty code modification hint, indicating that no code
65193326Sed  /// modification is known.
66234353Sdim  FixItHint() : BeforePreviousInsertions(false) { }
67193326Sed
68199482Srdivacky  bool isNull() const {
69212904Sdim    return !RemoveRange.isValid();
70199482Srdivacky  }
71199482Srdivacky
72193326Sed  /// \brief Create a code modification hint that inserts the given
73193326Sed  /// code string at a specific location.
74206084Srdivacky  static FixItHint CreateInsertion(SourceLocation InsertionLoc,
75234353Sdim                                   StringRef Code,
76234353Sdim                                   bool BeforePreviousInsertions = false) {
77206084Srdivacky    FixItHint Hint;
78212904Sdim    Hint.RemoveRange =
79249423Sdim      CharSourceRange::getCharRange(InsertionLoc, InsertionLoc);
80193326Sed    Hint.CodeToInsert = Code;
81234353Sdim    Hint.BeforePreviousInsertions = BeforePreviousInsertions;
82193326Sed    return Hint;
83193326Sed  }
84234353Sdim
85234353Sdim  /// \brief Create a code modification hint that inserts the given
86239462Sdim  /// code from \p FromRange at a specific location.
87234353Sdim  static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc,
88234353Sdim                                            CharSourceRange FromRange,
89234353Sdim                                        bool BeforePreviousInsertions = false) {
90234353Sdim    FixItHint Hint;
91234353Sdim    Hint.RemoveRange =
92249423Sdim      CharSourceRange::getCharRange(InsertionLoc, InsertionLoc);
93234353Sdim    Hint.InsertFromRange = FromRange;
94234353Sdim    Hint.BeforePreviousInsertions = BeforePreviousInsertions;
95234353Sdim    return Hint;
96234353Sdim  }
97193326Sed
98193326Sed  /// \brief Create a code modification hint that removes the given
99193326Sed  /// source range.
100210299Sed  static FixItHint CreateRemoval(CharSourceRange RemoveRange) {
101206084Srdivacky    FixItHint Hint;
102193326Sed    Hint.RemoveRange = RemoveRange;
103193326Sed    return Hint;
104193326Sed  }
105210299Sed  static FixItHint CreateRemoval(SourceRange RemoveRange) {
106210299Sed    return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange));
107210299Sed  }
108210299Sed
109193326Sed  /// \brief Create a code modification hint that replaces the given
110193326Sed  /// source range with the given code string.
111210299Sed  static FixItHint CreateReplacement(CharSourceRange RemoveRange,
112226633Sdim                                     StringRef Code) {
113206084Srdivacky    FixItHint Hint;
114193326Sed    Hint.RemoveRange = RemoveRange;
115193326Sed    Hint.CodeToInsert = Code;
116193326Sed    return Hint;
117193326Sed  }
118210299Sed
119210299Sed  static FixItHint CreateReplacement(SourceRange RemoveRange,
120226633Sdim                                     StringRef Code) {
121210299Sed    return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
122210299Sed  }
123193326Sed};
124193326Sed
125239462Sdim/// \brief Concrete class used by the front-end to report problems and issues.
126239462Sdim///
127239462Sdim/// This massages the diagnostics (e.g. handling things like "report warnings
128239462Sdim/// as errors" and passes them off to the DiagnosticConsumer for reporting to
129239462Sdim/// the user. DiagnosticsEngine is tied to one translation unit and one
130239462Sdim/// SourceManager.
131234353Sdimclass DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> {
132193326Sedpublic:
133239462Sdim  /// \brief The level of the diagnostic, after it has been through mapping.
134193326Sed  enum Level {
135218893Sdim    Ignored = DiagnosticIDs::Ignored,
136218893Sdim    Note = DiagnosticIDs::Note,
137218893Sdim    Warning = DiagnosticIDs::Warning,
138218893Sdim    Error = DiagnosticIDs::Error,
139218893Sdim    Fatal = DiagnosticIDs::Fatal
140193326Sed  };
141198092Srdivacky
142239462Sdim  /// \brief How do we handle otherwise-unmapped extension?
143239462Sdim  ///
144239462Sdim  /// This is controlled by -pedantic and -pedantic-errors.
145193326Sed  enum ExtensionHandling {
146193326Sed    Ext_Ignore, Ext_Warn, Ext_Error
147193326Sed  };
148198092Srdivacky
149193326Sed  enum ArgumentKind {
150239462Sdim    ak_std_string,      ///< std::string
151239462Sdim    ak_c_string,        ///< const char *
152239462Sdim    ak_sint,            ///< int
153239462Sdim    ak_uint,            ///< unsigned
154239462Sdim    ak_identifierinfo,  ///< IdentifierInfo
155239462Sdim    ak_qualtype,        ///< QualType
156239462Sdim    ak_declarationname, ///< DeclarationName
157239462Sdim    ak_nameddecl,       ///< NamedDecl *
158239462Sdim    ak_nestednamespec,  ///< NestedNameSpecifier *
159239462Sdim    ak_declcontext,     ///< DeclContext *
160239462Sdim    ak_qualtype_pair    ///< pair<QualType, QualType>
161193326Sed  };
162210299Sed
163239462Sdim  /// \brief Represents on argument value, which is a union discriminated
164239462Sdim  /// by ArgumentKind, with a value.
165198398Srdivacky  typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
166193326Sed
167198092Srdivackyprivate:
168193326Sed  unsigned char AllExtensionsSilenced; // Used by __extension__
169193326Sed  bool IgnoreAllWarnings;        // Ignore all warnings: -w
170226633Sdim  bool WarningsAsErrors;         // Treat warnings like errors.
171226633Sdim  bool EnableAllWarnings;        // Enable all warnings.
172201361Srdivacky  bool ErrorsAsFatal;            // Treat errors like fatal errors.
173193326Sed  bool SuppressSystemWarnings;   // Suppress warnings in system headers.
174198092Srdivacky  bool SuppressAllDiagnostics;   // Suppress all diagnostics.
175239462Sdim  bool ElideType;                // Elide common types of templates.
176239462Sdim  bool PrintTemplateTree;        // Print a tree when comparing templates.
177239462Sdim  bool ShowColors;               // Color printing is enabled.
178210299Sed  OverloadsShown ShowOverloads;  // Which overload candidates to show.
179207619Srdivacky  unsigned ErrorLimit;           // Cap of # errors emitted, 0 -> no limit.
180207619Srdivacky  unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
181207619Srdivacky                                   // 0 -> no limit.
182234353Sdim  unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation
183234353Sdim                                    // backtrace stack, 0 -> no limit.
184193326Sed  ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
185234353Sdim  IntrusiveRefCntPtr<DiagnosticIDs> Diags;
186243830Sdim  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts;
187226633Sdim  DiagnosticConsumer *Client;
188218893Sdim  bool OwnsDiagClient;
189218893Sdim  SourceManager *SourceMgr;
190218893Sdim
191239462Sdim  /// \brief Mapping information for diagnostics.
192218893Sdim  ///
193239462Sdim  /// Mapping info is packed into four bits per diagnostic.  The low three
194239462Sdim  /// bits are the mapping (an instance of diag::Mapping), or zero if unset.
195239462Sdim  /// The high bit is set when the mapping was established as a user mapping.
196239462Sdim  /// If the high bit is clear, then the low bits are set to the default
197239462Sdim  /// value, and should be mapped with -pedantic, -Werror, etc.
198239462Sdim  ///
199218893Sdim  /// A new DiagState is created and kept around when diagnostic pragmas modify
200218893Sdim  /// the state so that we know what is the diagnostic state at any given
201218893Sdim  /// source location.
202218893Sdim  class DiagState {
203226633Sdim    llvm::DenseMap<unsigned, DiagnosticMappingInfo> DiagMap;
204198092Srdivacky
205212904Sdim  public:
206226633Sdim    typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::iterator
207226633Sdim      iterator;
208226633Sdim    typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::const_iterator
209226633Sdim      const_iterator;
210212904Sdim
211226633Sdim    void setMappingInfo(diag::kind Diag, DiagnosticMappingInfo Info) {
212226633Sdim      DiagMap[Diag] = Info;
213212904Sdim    }
214218893Sdim
215226633Sdim    DiagnosticMappingInfo &getOrAddMappingInfo(diag::kind Diag);
216226633Sdim
217226633Sdim    const_iterator begin() const { return DiagMap.begin(); }
218226633Sdim    const_iterator end() const { return DiagMap.end(); }
219212904Sdim  };
220212904Sdim
221218893Sdim  /// \brief Keeps and automatically disposes all DiagStates that we create.
222218893Sdim  std::list<DiagState> DiagStates;
223198092Srdivacky
224218893Sdim  /// \brief Represents a point in source where the diagnostic state was
225239462Sdim  /// modified because of a pragma.
226239462Sdim  ///
227239462Sdim  /// 'Loc' can be null if the point represents the diagnostic state
228239462Sdim  /// modifications done through the command-line.
229218893Sdim  struct DiagStatePoint {
230218893Sdim    DiagState *State;
231218893Sdim    FullSourceLoc Loc;
232218893Sdim    DiagStatePoint(DiagState *State, FullSourceLoc Loc)
233218893Sdim      : State(State), Loc(Loc) { }
234218893Sdim
235218893Sdim    bool operator<(const DiagStatePoint &RHS) const {
236218893Sdim      // If Loc is invalid it means it came from <command-line>, in which case
237218893Sdim      // we regard it as coming before any valid source location.
238218893Sdim      if (RHS.Loc.isInvalid())
239218893Sdim        return false;
240218893Sdim      if (Loc.isInvalid())
241218893Sdim        return true;
242218893Sdim      return Loc.isBeforeInTranslationUnitThan(RHS.Loc);
243218893Sdim    }
244218893Sdim  };
245218893Sdim
246239462Sdim  /// \brief A sorted vector of all DiagStatePoints representing changes in
247239462Sdim  /// diagnostic state due to diagnostic pragmas.
248239462Sdim  ///
249239462Sdim  /// The vector is always sorted according to the SourceLocation of the
250239462Sdim  /// DiagStatePoint.
251218893Sdim  typedef std::vector<DiagStatePoint> DiagStatePointsTy;
252218893Sdim  mutable DiagStatePointsTy DiagStatePoints;
253218893Sdim
254218893Sdim  /// \brief Keeps the DiagState that was active during each diagnostic 'push'
255218893Sdim  /// so we can get back at it when we 'pop'.
256218893Sdim  std::vector<DiagState *> DiagStateOnPushStack;
257218893Sdim
258218893Sdim  DiagState *GetCurDiagState() const {
259218893Sdim    assert(!DiagStatePoints.empty());
260218893Sdim    return DiagStatePoints.back().State;
261218893Sdim  }
262218893Sdim
263218893Sdim  void PushDiagStatePoint(DiagState *State, SourceLocation L) {
264239462Sdim    FullSourceLoc Loc(L, getSourceManager());
265218893Sdim    // Make sure that DiagStatePoints is always sorted according to Loc.
266239462Sdim    assert(Loc.isValid() && "Adding invalid loc point");
267239462Sdim    assert(!DiagStatePoints.empty() &&
268239462Sdim           (DiagStatePoints.back().Loc.isInvalid() ||
269218893Sdim            DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) &&
270218893Sdim           "Previous point loc comes after or is the same as new one");
271239462Sdim    DiagStatePoints.push_back(DiagStatePoint(State, Loc));
272218893Sdim  }
273218893Sdim
274218893Sdim  /// \brief Finds the DiagStatePoint that contains the diagnostic state of
275218893Sdim  /// the given source location.
276218893Sdim  DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
277218893Sdim
278239462Sdim  /// \brief Sticky flag set to \c true when an error is emitted.
279193326Sed  bool ErrorOccurred;
280239462Sdim
281249423Sdim  /// \brief Sticky flag set to \c true when an "uncompilable error" occurs.
282249423Sdim  /// I.e. an error that was not upgraded from a warning by -Werror.
283249423Sdim  bool UncompilableErrorOccurred;
284249423Sdim
285239462Sdim  /// \brief Sticky flag set to \c true when a fatal error is emitted.
286193326Sed  bool FatalErrorOccurred;
287198092Srdivacky
288224145Sdim  /// \brief Indicates that an unrecoverable error has occurred.
289224145Sdim  bool UnrecoverableErrorOccurred;
290224145Sdim
291226633Sdim  /// \brief Counts for DiagnosticErrorTrap to check whether an error occurred
292224145Sdim  /// during a parsing section, e.g. during parsing a function.
293226633Sdim  unsigned TrapNumErrorsOccurred;
294226633Sdim  unsigned TrapNumUnrecoverableErrorsOccurred;
295224145Sdim
296239462Sdim  /// \brief The level of the last diagnostic emitted.
297239462Sdim  ///
298239462Sdim  /// This is used to emit continuation diagnostics with the same level as the
299193326Sed  /// diagnostic that they follow.
300218893Sdim  DiagnosticIDs::Level LastDiagLevel;
301193326Sed
302239462Sdim  unsigned NumWarnings;         ///< Number of warnings reported
303239462Sdim  unsigned NumErrors;           ///< Number of errors reported
304239462Sdim  unsigned NumErrorsSuppressed; ///< Number of errors suppressed
305193326Sed
306239462Sdim  /// \brief A function pointer that converts an opaque diagnostic
307239462Sdim  /// argument to a strings.
308198398Srdivacky  ///
309239462Sdim  /// This takes the modifiers and argument that was present in the diagnostic.
310239462Sdim  ///
311198398Srdivacky  /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
312198398Srdivacky  /// arguments formatted for this diagnostic.  Implementations of this function
313198398Srdivacky  /// can use this information to avoid redundancy across arguments.
314198398Srdivacky  ///
315193326Sed  /// This is a hack to avoid a layering violation between libbasic and libsema.
316224145Sdim  typedef void (*ArgToStringFnTy)(
317224145Sdim      ArgumentKind Kind, intptr_t Val,
318224145Sdim      const char *Modifier, unsigned ModifierLen,
319224145Sdim      const char *Argument, unsigned ArgumentLen,
320224145Sdim      const ArgumentValue *PrevArgs,
321224145Sdim      unsigned NumPrevArgs,
322226633Sdim      SmallVectorImpl<char> &Output,
323224145Sdim      void *Cookie,
324234353Sdim      ArrayRef<intptr_t> QualTypeVals);
325193326Sed  void *ArgToStringCookie;
326193326Sed  ArgToStringFnTy ArgToStringFn;
327206084Srdivacky
328206084Srdivacky  /// \brief ID of the "delayed" diagnostic, which is a (typically
329206084Srdivacky  /// fatal) diagnostic that had to be delayed because it was found
330206084Srdivacky  /// while emitting another diagnostic.
331206084Srdivacky  unsigned DelayedDiagID;
332206084Srdivacky
333206084Srdivacky  /// \brief First string argument for the delayed diagnostic.
334206084Srdivacky  std::string DelayedDiagArg1;
335206084Srdivacky
336206084Srdivacky  /// \brief Second string argument for the delayed diagnostic.
337206084Srdivacky  std::string DelayedDiagArg2;
338206084Srdivacky
339193326Sedpublic:
340226633Sdim  explicit DiagnosticsEngine(
341234353Sdim                      const IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
342243830Sdim                      DiagnosticOptions *DiagOpts,
343226633Sdim                      DiagnosticConsumer *client = 0,
344218893Sdim                      bool ShouldOwnClient = true);
345226633Sdim  ~DiagnosticsEngine();
346198092Srdivacky
347234353Sdim  const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
348218893Sdim    return Diags;
349218893Sdim  }
350218893Sdim
351243830Sdim  /// \brief Retrieve the diagnostic options.
352243830Sdim  DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; }
353243830Sdim
354226633Sdim  DiagnosticConsumer *getClient() { return Client; }
355226633Sdim  const DiagnosticConsumer *getClient() const { return Client; }
356218893Sdim
357226633Sdim  /// \brief Determine whether this \c DiagnosticsEngine object own its client.
358226633Sdim  bool ownsClient() const { return OwnsDiagClient; }
359226633Sdim
360218893Sdim  /// \brief Return the current diagnostic client along with ownership of that
361218893Sdim  /// client.
362226633Sdim  DiagnosticConsumer *takeClient() {
363218893Sdim    OwnsDiagClient = false;
364218893Sdim    return Client;
365218893Sdim  }
366218893Sdim
367218893Sdim  bool hasSourceManager() const { return SourceMgr != 0; }
368218893Sdim  SourceManager &getSourceManager() const {
369218893Sdim    assert(SourceMgr && "SourceManager not set!");
370218893Sdim    return *SourceMgr;
371218893Sdim  }
372218893Sdim  void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
373218893Sdim
374193326Sed  //===--------------------------------------------------------------------===//
375226633Sdim  //  DiagnosticsEngine characterization methods, used by a client to customize
376226633Sdim  //  how diagnostics are emitted.
377193326Sed  //
378198092Srdivacky
379239462Sdim  /// \brief Copies the current DiagMappings and pushes the new copy
380198092Srdivacky  /// onto the top of the stack.
381218893Sdim  void pushMappings(SourceLocation Loc);
382198092Srdivacky
383239462Sdim  /// \brief Pops the current DiagMappings off the top of the stack,
384239462Sdim  /// causing the new top of the stack to be the active mappings.
385239462Sdim  ///
386239462Sdim  /// \returns \c true if the pop happens, \c false if there is only one
387239462Sdim  /// DiagMapping on the stack.
388218893Sdim  bool popMappings(SourceLocation Loc);
389198092Srdivacky
390212904Sdim  /// \brief Set the diagnostic client associated with this diagnostic object.
391212904Sdim  ///
392218893Sdim  /// \param ShouldOwnClient true if the diagnostic object should take
393218893Sdim  /// ownership of \c client.
394226633Sdim  void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true);
395193326Sed
396239462Sdim  /// \brief Specify a limit for the number of errors we should
397239462Sdim  /// emit before giving up.
398239462Sdim  ///
399239462Sdim  /// Zero disables the limit.
400207619Srdivacky  void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }
401207619Srdivacky
402207619Srdivacky  /// \brief Specify the maximum number of template instantiation
403207619Srdivacky  /// notes to emit along with a given diagnostic.
404207619Srdivacky  void setTemplateBacktraceLimit(unsigned Limit) {
405207619Srdivacky    TemplateBacktraceLimit = Limit;
406207619Srdivacky  }
407234353Sdim
408207619Srdivacky  /// \brief Retrieve the maximum number of template instantiation
409234353Sdim  /// notes to emit along with a given diagnostic.
410207619Srdivacky  unsigned getTemplateBacktraceLimit() const {
411207619Srdivacky    return TemplateBacktraceLimit;
412207619Srdivacky  }
413234353Sdim
414234353Sdim  /// \brief Specify the maximum number of constexpr evaluation
415234353Sdim  /// notes to emit along with a given diagnostic.
416234353Sdim  void setConstexprBacktraceLimit(unsigned Limit) {
417234353Sdim    ConstexprBacktraceLimit = Limit;
418234353Sdim  }
419234353Sdim
420234353Sdim  /// \brief Retrieve the maximum number of constexpr evaluation
421234353Sdim  /// notes to emit along with a given diagnostic.
422234353Sdim  unsigned getConstexprBacktraceLimit() const {
423234353Sdim    return ConstexprBacktraceLimit;
424234353Sdim  }
425234353Sdim
426239462Sdim  /// \brief When set to true, any unmapped warnings are ignored.
427239462Sdim  ///
428239462Sdim  /// If this and WarningsAsErrors are both set, then this one wins.
429193326Sed  void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
430193326Sed  bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
431198092Srdivacky
432239462Sdim  /// \brief When set to true, any unmapped ignored warnings are no longer
433239462Sdim  /// ignored.
434239462Sdim  ///
435239462Sdim  /// If this and IgnoreAllWarnings are both set, then that one wins.
436226633Sdim  void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; }
437249423Sdim  bool getEnableAllWarnings() const { return EnableAllWarnings; }
438249423Sdim
439239462Sdim  /// \brief When set to true, any warnings reported are issued as errors.
440193326Sed  void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
441193326Sed  bool getWarningsAsErrors() const { return WarningsAsErrors; }
442198092Srdivacky
443239462Sdim  /// \brief When set to true, any error reported is made a fatal error.
444201361Srdivacky  void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
445201361Srdivacky  bool getErrorsAsFatal() const { return ErrorsAsFatal; }
446201361Srdivacky
447239462Sdim  /// \brief When set to true mask warnings that come from system headers.
448193326Sed  void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
449193326Sed  bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
450193326Sed
451198092Srdivacky  /// \brief Suppress all diagnostics, to silence the front end when we
452198092Srdivacky  /// know that we don't want any more diagnostics to be passed along to the
453198092Srdivacky  /// client
454198092Srdivacky  void setSuppressAllDiagnostics(bool Val = true) {
455198092Srdivacky    SuppressAllDiagnostics = Val;
456198092Srdivacky  }
457198092Srdivacky  bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
458239462Sdim
459239462Sdim  /// \brief Set type eliding, to skip outputting same types occurring in
460239462Sdim  /// template types.
461239462Sdim  void setElideType(bool Val = true) { ElideType = Val; }
462239462Sdim  bool getElideType() { return ElideType; }
463239462Sdim
464239462Sdim  /// \brief Set tree printing, to outputting the template difference in a
465239462Sdim  /// tree format.
466239462Sdim  void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; }
467239462Sdim  bool getPrintTemplateTree() { return PrintTemplateTree; }
468239462Sdim
469239462Sdim  /// \brief Set color printing, so the type diffing will inject color markers
470239462Sdim  /// into the output.
471239462Sdim  void setShowColors(bool Val = false) { ShowColors = Val; }
472239462Sdim  bool getShowColors() { return ShowColors; }
473239462Sdim
474210299Sed  /// \brief Specify which overload candidates to show when overload resolution
475239462Sdim  /// fails.
476239462Sdim  ///
477239462Sdim  /// By default, we show all candidates.
478210299Sed  void setShowOverloads(OverloadsShown Val) {
479210299Sed    ShowOverloads = Val;
480210299Sed  }
481210299Sed  OverloadsShown getShowOverloads() const { return ShowOverloads; }
482210299Sed
483243830Sdim  /// \brief Pretend that the last diagnostic issued was ignored, so any
484243830Sdim  /// subsequent notes will be suppressed.
485239462Sdim  ///
486239462Sdim  /// This can be used by clients who suppress diagnostics themselves.
487198092Srdivacky  void setLastDiagnosticIgnored() {
488243830Sdim    if (LastDiagLevel == DiagnosticIDs::Fatal)
489243830Sdim      FatalErrorOccurred = true;
490218893Sdim    LastDiagLevel = DiagnosticIDs::Ignored;
491198092Srdivacky  }
492263508Sdim
493263508Sdim  /// \brief Determine whether the previous diagnostic was ignored. This can
494263508Sdim  /// be used by clients that want to determine whether notes attached to a
495263508Sdim  /// diagnostic will be suppressed.
496263508Sdim  bool isLastDiagnosticIgnored() const {
497263508Sdim    return LastDiagLevel == DiagnosticIDs::Ignored;
498263508Sdim  }
499263508Sdim
500239462Sdim  /// \brief Controls whether otherwise-unmapped extension diagnostics are
501239462Sdim  /// mapped onto ignore/warning/error.
502239462Sdim  ///
503239462Sdim  /// This corresponds to the GCC -pedantic and -pedantic-errors option.
504193326Sed  void setExtensionHandlingBehavior(ExtensionHandling H) {
505193326Sed    ExtBehavior = H;
506193326Sed  }
507223017Sdim  ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; }
508198092Srdivacky
509239462Sdim  /// \brief Counter bumped when an __extension__  block is/ encountered.
510239462Sdim  ///
511239462Sdim  /// When non-zero, all extension diagnostics are entirely silenced, no
512239462Sdim  /// matter how they are mapped.
513193326Sed  void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
514193326Sed  void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
515198092Srdivacky  bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
516198092Srdivacky
517239462Sdim  /// \brief This allows the client to specify that certain warnings are
518239462Sdim  /// ignored.
519218893Sdim  ///
520239462Sdim  /// Notes can never be mapped, errors can only be mapped to fatal, and
521239462Sdim  /// WARNINGs and EXTENSIONs can be mapped arbitrarily.
522239462Sdim  ///
523218893Sdim  /// \param Loc The source location that this change of diagnostic state should
524218893Sdim  /// take affect. It can be null if we are setting the latest state.
525218893Sdim  void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
526218893Sdim                            SourceLocation Loc);
527198092Srdivacky
528239462Sdim  /// \brief Change an entire diagnostic group (e.g. "unknown-pragmas") to
529239462Sdim  /// have the specified mapping.
530218893Sdim  ///
531239462Sdim  /// \returns true (and ignores the request) if "Group" was unknown, false
532239462Sdim  /// otherwise.
533239462Sdim  ///
534239462Sdim  /// \param Loc The source location that this change of diagnostic state should
535218893Sdim  /// take affect. It can be null if we are setting the state from command-line.
536226633Sdim  bool setDiagnosticGroupMapping(StringRef Group, diag::Mapping Map,
537226633Sdim                                 SourceLocation Loc = SourceLocation());
538193326Sed
539239462Sdim  /// \brief Set the warning-as-error flag for the given diagnostic.
540239462Sdim  ///
541239462Sdim  /// This function always only operates on the current diagnostic state.
542234353Sdim  void setDiagnosticWarningAsError(diag::kind Diag, bool Enabled);
543234353Sdim
544239462Sdim  /// \brief Set the warning-as-error flag for the given diagnostic group.
545226633Sdim  ///
546239462Sdim  /// This function always only operates on the current diagnostic state.
547239462Sdim  ///
548226633Sdim  /// \returns True if the given group is unknown, false otherwise.
549226633Sdim  bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled);
550226633Sdim
551239462Sdim  /// \brief Set the error-as-fatal flag for the given diagnostic.
552239462Sdim  ///
553239462Sdim  /// This function always only operates on the current diagnostic state.
554234353Sdim  void setDiagnosticErrorAsFatal(diag::kind Diag, bool Enabled);
555234353Sdim
556239462Sdim  /// \brief Set the error-as-fatal flag for the given diagnostic group.
557226633Sdim  ///
558239462Sdim  /// This function always only operates on the current diagnostic state.
559239462Sdim  ///
560226633Sdim  /// \returns True if the given group is unknown, false otherwise.
561226633Sdim  bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);
562226633Sdim
563239462Sdim  /// \brief Add the specified mapping to all diagnostics.
564239462Sdim  ///
565239462Sdim  /// Mainly to be used by -Wno-everything to disable all warnings but allow
566239462Sdim  /// subsequent -W options to enable specific warnings.
567234353Sdim  void setMappingToAllDiagnostics(diag::Mapping Map,
568234353Sdim                                  SourceLocation Loc = SourceLocation());
569234353Sdim
570193326Sed  bool hasErrorOccurred() const { return ErrorOccurred; }
571249423Sdim
572249423Sdim  /// \brief Errors that actually prevent compilation, not those that are
573249423Sdim  /// upgraded from a warning by -Werror.
574249423Sdim  bool hasUncompilableErrorOccurred() const {
575249423Sdim    return UncompilableErrorOccurred;
576249423Sdim  }
577193326Sed  bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
578224145Sdim
579224145Sdim  /// \brief Determine whether any kind of unrecoverable error has occurred.
580224145Sdim  bool hasUnrecoverableErrorOccurred() const {
581224145Sdim    return FatalErrorOccurred || UnrecoverableErrorOccurred;
582224145Sdim  }
583224145Sdim
584207619Srdivacky  unsigned getNumWarnings() const { return NumWarnings; }
585198092Srdivacky
586212904Sdim  void setNumWarnings(unsigned NumWarnings) {
587212904Sdim    this->NumWarnings = NumWarnings;
588212904Sdim  }
589212904Sdim
590239462Sdim  /// \brief Return an ID for a diagnostic with the specified message and level.
591239462Sdim  ///
592249423Sdim  /// If this is the first request for this diagnostic, it is registered and
593239462Sdim  /// created, otherwise the existing ID is returned.
594226633Sdim  unsigned getCustomDiagID(Level L, StringRef Message) {
595218893Sdim    return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
596218893Sdim  }
597198092Srdivacky
598239462Sdim  /// \brief Converts a diagnostic argument (as an intptr_t) into the string
599239462Sdim  /// that represents it.
600193326Sed  void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
601193326Sed                          const char *Modifier, unsigned ModLen,
602193326Sed                          const char *Argument, unsigned ArgLen,
603198398Srdivacky                          const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
604226633Sdim                          SmallVectorImpl<char> &Output,
605243830Sdim                          ArrayRef<intptr_t> QualTypeVals) const {
606198398Srdivacky    ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
607224145Sdim                  PrevArgs, NumPrevArgs, Output, ArgToStringCookie,
608224145Sdim                  QualTypeVals);
609193326Sed  }
610198092Srdivacky
611193326Sed  void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
612193326Sed    ArgToStringFn = Fn;
613193326Sed    ArgToStringCookie = Cookie;
614193326Sed  }
615198092Srdivacky
616249423Sdim  /// \brief Note that the prior diagnostic was emitted by some other
617249423Sdim  /// \c DiagnosticsEngine, and we may be attaching a note to that diagnostic.
618249423Sdim  void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) {
619249423Sdim    LastDiagLevel = Other.LastDiagLevel;
620249423Sdim  }
621249423Sdim
622212904Sdim  /// \brief Reset the state of the diagnostic object to its initial
623212904Sdim  /// configuration.
624212904Sdim  void Reset();
625212904Sdim
626193326Sed  //===--------------------------------------------------------------------===//
627226633Sdim  // DiagnosticsEngine classification and reporting interfaces.
628193326Sed  //
629193326Sed
630226633Sdim  /// \brief Based on the way the client configured the DiagnosticsEngine
631218893Sdim  /// object, classify the specified diagnostic ID into a Level, consumable by
632226633Sdim  /// the DiagnosticConsumer.
633193326Sed  ///
634218893Sdim  /// \param Loc The source location we are interested in finding out the
635218893Sdim  /// diagnostic state. Can be null in order to query the latest state.
636226633Sdim  Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
637226633Sdim    return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
638207619Srdivacky  }
639198092Srdivacky
640239462Sdim  /// \brief Issue the message to the client.
641239462Sdim  ///
642239462Sdim  /// This actually returns an instance of DiagnosticBuilder which emits the
643239462Sdim  /// diagnostics (through @c ProcessDiag) when it is destroyed.
644239462Sdim  ///
645239462Sdim  /// \param DiagID A member of the @c diag::kind enum.
646239462Sdim  /// \param Loc Represents the source location associated with the diagnostic,
647193326Sed  /// which can be an invalid location if no position information is available.
648239462Sdim  inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID);
649199482Srdivacky  inline DiagnosticBuilder Report(unsigned DiagID);
650193326Sed
651223017Sdim  void Report(const StoredDiagnostic &storedDiag);
652223017Sdim
653206084Srdivacky  /// \brief Determine whethere there is already a diagnostic in flight.
654206084Srdivacky  bool isDiagnosticInFlight() const { return CurDiagID != ~0U; }
655206084Srdivacky
656206084Srdivacky  /// \brief Set the "delayed" diagnostic that will be emitted once
657206084Srdivacky  /// the current diagnostic completes.
658206084Srdivacky  ///
659206084Srdivacky  ///  If a diagnostic is already in-flight but the front end must
660206084Srdivacky  ///  report a problem (e.g., with an inconsistent file system
661206084Srdivacky  ///  state), this routine sets a "delayed" diagnostic that will be
662206084Srdivacky  ///  emitted after the current diagnostic completes. This should
663206084Srdivacky  ///  only be used for fatal errors detected at inconvenient
664206084Srdivacky  ///  times. If emitting a delayed diagnostic causes a second delayed
665206084Srdivacky  ///  diagnostic to be introduced, that second delayed diagnostic
666206084Srdivacky  ///  will be ignored.
667206084Srdivacky  ///
668206084Srdivacky  /// \param DiagID The ID of the diagnostic being delayed.
669206084Srdivacky  ///
670206084Srdivacky  /// \param Arg1 A string argument that will be provided to the
671206084Srdivacky  /// diagnostic. A copy of this string will be stored in the
672226633Sdim  /// DiagnosticsEngine object itself.
673206084Srdivacky  ///
674206084Srdivacky  /// \param Arg2 A string argument that will be provided to the
675206084Srdivacky  /// diagnostic. A copy of this string will be stored in the
676226633Sdim  /// DiagnosticsEngine object itself.
677226633Sdim  void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
678226633Sdim                            StringRef Arg2 = "");
679206084Srdivacky
680193326Sed  /// \brief Clear out the current diagnostic.
681193326Sed  void Clear() { CurDiagID = ~0U; }
682198092Srdivacky
683193326Sedprivate:
684206084Srdivacky  /// \brief Report the delayed diagnostic.
685206084Srdivacky  void ReportDelayed();
686206084Srdivacky
687193326Sed  // This is private state used by DiagnosticBuilder.  We put it here instead of
688193326Sed  // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
689193326Sed  // object.  This implementation choice means that we can only have one
690193326Sed  // diagnostic "in flight" at a time, but this seems to be a reasonable
691193326Sed  // tradeoff to keep these objects small.  Assertions verify that only one
692193326Sed  // diagnostic is in flight at a time.
693218893Sdim  friend class DiagnosticIDs;
694193326Sed  friend class DiagnosticBuilder;
695226633Sdim  friend class Diagnostic;
696218893Sdim  friend class PartialDiagnostic;
697218893Sdim  friend class DiagnosticErrorTrap;
698218893Sdim
699239462Sdim  /// \brief The location of the current diagnostic that is in flight.
700218893Sdim  SourceLocation CurDiagLoc;
701198092Srdivacky
702239462Sdim  /// \brief The ID of the current diagnostic that is in flight.
703239462Sdim  ///
704193326Sed  /// This is set to ~0U when there is no diagnostic in flight.
705193326Sed  unsigned CurDiagID;
706193326Sed
707193326Sed  enum {
708239462Sdim    /// \brief The maximum number of arguments we can hold.
709239462Sdim    ///
710239462Sdim    /// We currently only support up to 10 arguments (%0-%9).  A single
711239462Sdim    /// diagnostic with more than that almost certainly has to be simplified
712239462Sdim    /// anyway.
713234353Sdim    MaxArguments = 10,
714234353Sdim
715239462Sdim    /// \brief The maximum number of ranges we can hold.
716234353Sdim    MaxRanges = 10,
717234353Sdim
718239462Sdim    /// \brief The maximum number of ranges we can hold.
719234353Sdim    MaxFixItHints = 10
720193326Sed  };
721198092Srdivacky
722239462Sdim  /// \brief The number of entries in Arguments.
723193326Sed  signed char NumDiagArgs;
724239462Sdim  /// \brief The number of ranges in the DiagRanges array.
725193326Sed  unsigned char NumDiagRanges;
726239462Sdim  /// \brief The number of hints in the DiagFixItHints array.
727234353Sdim  unsigned char NumDiagFixItHints;
728193326Sed
729239462Sdim  /// \brief Specifies whether an argument is in DiagArgumentsStr or
730239462Sdim  /// in DiagArguments.
731239462Sdim  ///
732239462Sdim  /// This is an array of ArgumentKind::ArgumentKind enum values, one for each
733239462Sdim  /// argument.
734193326Sed  unsigned char DiagArgumentsKind[MaxArguments];
735198092Srdivacky
736239462Sdim  /// \brief Holds the values of each string argument for the current
737239462Sdim  /// diagnostic.
738239462Sdim  ///
739239462Sdim  /// This is only used when the corresponding ArgumentKind is ak_std_string.
740193326Sed  std::string DiagArgumentsStr[MaxArguments];
741193326Sed
742239462Sdim  /// \brief The values for the various substitution positions.
743239462Sdim  ///
744239462Sdim  /// This is used when the argument is not an std::string.  The specific
745239462Sdim  /// value is mangled into an intptr_t and the interpretation depends on
746239462Sdim  /// exactly what sort of argument kind it is.
747193326Sed  intptr_t DiagArgumentsVal[MaxArguments];
748198092Srdivacky
749239462Sdim  /// \brief The list of ranges added to this diagnostic.
750234353Sdim  CharSourceRange DiagRanges[MaxRanges];
751198092Srdivacky
752239462Sdim  /// \brief If valid, provides a hint with some code to insert, remove,
753234353Sdim  /// or modify at a particular position.
754234353Sdim  FixItHint DiagFixItHints[MaxFixItHints];
755193326Sed
756234353Sdim  DiagnosticMappingInfo makeMappingInfo(diag::Mapping Map, SourceLocation L) {
757234353Sdim    bool isPragma = L.isValid();
758234353Sdim    DiagnosticMappingInfo MappingInfo = DiagnosticMappingInfo::Make(
759234353Sdim      Map, /*IsUser=*/true, isPragma);
760193326Sed
761234353Sdim    // If this is a pragma mapping, then set the diagnostic mapping flags so
762234353Sdim    // that we override command line options.
763234353Sdim    if (isPragma) {
764234353Sdim      MappingInfo.setNoWarningAsError(true);
765234353Sdim      MappingInfo.setNoErrorAsFatal(true);
766234353Sdim    }
767234353Sdim
768234353Sdim    return MappingInfo;
769234353Sdim  }
770234353Sdim
771239462Sdim  /// \brief Used to report a diagnostic that is finally fully formed.
772194179Sed  ///
773239462Sdim  /// \returns true if the diagnostic was emitted, false if it was suppressed.
774218893Sdim  bool ProcessDiag() {
775218893Sdim    return Diags->ProcessDiag(*this);
776218893Sdim  }
777218893Sdim
778234353Sdim  /// @name Diagnostic Emission
779234353Sdim  /// @{
780234353Sdimprotected:
781234353Sdim  // Sema requires access to the following functions because the current design
782234353Sdim  // of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to
783234353Sdim  // access us directly to ensure we minimize the emitted code for the common
784234353Sdim  // Sema::Diag() patterns.
785234353Sdim  friend class Sema;
786234353Sdim
787234353Sdim  /// \brief Emit the current diagnostic and clear the diagnostic state.
788239462Sdim  ///
789239462Sdim  /// \param Force Emit the diagnostic regardless of suppression settings.
790239462Sdim  bool EmitCurrentDiagnostic(bool Force = false);
791234353Sdim
792234353Sdim  unsigned getCurrentDiagID() const { return CurDiagID; }
793234353Sdim
794234353Sdim  SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; }
795234353Sdim
796234353Sdim  /// @}
797234353Sdim
798218893Sdim  friend class ASTReader;
799218893Sdim  friend class ASTWriter;
800193326Sed};
801193326Sed
802218893Sdim/// \brief RAII class that determines when any errors have occurred
803218893Sdim/// between the time the instance was created and the time it was
804218893Sdim/// queried.
805218893Sdimclass DiagnosticErrorTrap {
806226633Sdim  DiagnosticsEngine &Diag;
807226633Sdim  unsigned NumErrors;
808226633Sdim  unsigned NumUnrecoverableErrors;
809218893Sdim
810218893Sdimpublic:
811226633Sdim  explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag)
812224145Sdim    : Diag(Diag) { reset(); }
813218893Sdim
814218893Sdim  /// \brief Determine whether any errors have occurred since this
815218893Sdim  /// object instance was created.
816218893Sdim  bool hasErrorOccurred() const {
817226633Sdim    return Diag.TrapNumErrorsOccurred > NumErrors;
818218893Sdim  }
819218893Sdim
820224145Sdim  /// \brief Determine whether any unrecoverable errors have occurred since this
821224145Sdim  /// object instance was created.
822224145Sdim  bool hasUnrecoverableErrorOccurred() const {
823226633Sdim    return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
824224145Sdim  }
825224145Sdim
826239462Sdim  /// \brief Set to initial state of "no errors occurred".
827224145Sdim  void reset() {
828226633Sdim    NumErrors = Diag.TrapNumErrorsOccurred;
829226633Sdim    NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
830224145Sdim  }
831218893Sdim};
832218893Sdim
833193326Sed//===----------------------------------------------------------------------===//
834193326Sed// DiagnosticBuilder
835193326Sed//===----------------------------------------------------------------------===//
836193326Sed
837239462Sdim/// \brief A little helper class used to produce diagnostics.
838193326Sed///
839239462Sdim/// This is constructed by the DiagnosticsEngine::Report method, and
840239462Sdim/// allows insertion of extra information (arguments and source ranges) into
841239462Sdim/// the currently "in flight" diagnostic.  When the temporary for the builder
842239462Sdim/// is destroyed, the diagnostic is issued.
843239462Sdim///
844193326Sed/// Note that many of these will be created as temporary objects (many call
845193326Sed/// sites), so we want them to be small and we never want their address taken.
846193326Sed/// This ensures that compilers with somewhat reasonable optimizers will promote
847193326Sed/// the common fields to registers, eliminating increments of the NumArgs field,
848193326Sed/// for example.
849193326Sedclass DiagnosticBuilder {
850226633Sdim  mutable DiagnosticsEngine *DiagObj;
851234353Sdim  mutable unsigned NumArgs, NumRanges, NumFixits;
852198092Srdivacky
853234353Sdim  /// \brief Status variable indicating if this diagnostic is still active.
854234353Sdim  ///
855234353Sdim  // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)),
856234353Sdim  // but LLVM is not currently smart enough to eliminate the null check that
857234353Sdim  // Emit() would end up with if we used that as our status variable.
858234353Sdim  mutable bool IsActive;
859234353Sdim
860239462Sdim  /// \brief Flag indicating that this diagnostic is being emitted via a
861239462Sdim  /// call to ForceEmit.
862239462Sdim  mutable bool IsForceEmit;
863239462Sdim
864243830Sdim  void operator=(const DiagnosticBuilder &) LLVM_DELETED_FUNCTION;
865226633Sdim  friend class DiagnosticsEngine;
866239462Sdim
867239462Sdim  DiagnosticBuilder()
868239462Sdim    : DiagObj(0), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(false),
869239462Sdim      IsForceEmit(false) { }
870239462Sdim
871226633Sdim  explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
872239462Sdim    : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixits(0), IsActive(true),
873239462Sdim      IsForceEmit(false) {
874234353Sdim    assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!");
875234353Sdim  }
876193326Sed
877218893Sdim  friend class PartialDiagnostic;
878239462Sdim
879218893Sdimprotected:
880234353Sdim  void FlushCounts() {
881234353Sdim    DiagObj->NumDiagArgs = NumArgs;
882234353Sdim    DiagObj->NumDiagRanges = NumRanges;
883234353Sdim    DiagObj->NumDiagFixItHints = NumFixits;
884193326Sed  }
885193326Sed
886234353Sdim  /// \brief Clear out the current diagnostic.
887234353Sdim  void Clear() const {
888234353Sdim    DiagObj = 0;
889234353Sdim    IsActive = false;
890239462Sdim    IsForceEmit = false;
891234353Sdim  }
892194179Sed
893239462Sdim  /// \brief Determine whether this diagnostic is still active.
894234353Sdim  bool isActive() const { return IsActive; }
895194179Sed
896193326Sed  /// \brief Force the diagnostic builder to emit the diagnostic now.
897193326Sed  ///
898193326Sed  /// Once this function has been called, the DiagnosticBuilder object
899193326Sed  /// should not be used again before it is destroyed.
900194179Sed  ///
901194179Sed  /// \returns true if a diagnostic was emitted, false if the
902194179Sed  /// diagnostic was suppressed.
903234353Sdim  bool Emit() {
904234353Sdim    // If this diagnostic is inactive, then its soul was stolen by the copy ctor
905234353Sdim    // (or by a subclass, as in SemaDiagnosticBuilder).
906234353Sdim    if (!isActive()) return false;
907193326Sed
908234353Sdim    // When emitting diagnostics, we set the final argument count into
909234353Sdim    // the DiagnosticsEngine object.
910234353Sdim    FlushCounts();
911198092Srdivacky
912234353Sdim    // Process the diagnostic.
913239462Sdim    bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit);
914203955Srdivacky
915234353Sdim    // This diagnostic is dead.
916234353Sdim    Clear();
917234353Sdim
918234353Sdim    return Result;
919218893Sdim  }
920218893Sdim
921234353Sdimpublic:
922234353Sdim  /// Copy constructor.  When copied, this "takes" the diagnostic info from the
923234353Sdim  /// input and neuters it.
924234353Sdim  DiagnosticBuilder(const DiagnosticBuilder &D) {
925234353Sdim    DiagObj = D.DiagObj;
926234353Sdim    IsActive = D.IsActive;
927239462Sdim    IsForceEmit = D.IsForceEmit;
928234353Sdim    D.Clear();
929234353Sdim    NumArgs = D.NumArgs;
930234353Sdim    NumRanges = D.NumRanges;
931234353Sdim    NumFixits = D.NumFixits;
932234353Sdim  }
933234353Sdim
934239462Sdim  /// \brief Retrieve an empty diagnostic builder.
935239462Sdim  static DiagnosticBuilder getEmpty() {
936239462Sdim    return DiagnosticBuilder();
937239462Sdim  }
938239462Sdim
939239462Sdim  /// \brief Emits the diagnostic.
940234353Sdim  ~DiagnosticBuilder() {
941234353Sdim    Emit();
942234353Sdim  }
943218893Sdim
944239462Sdim  /// \brief Forces the diagnostic to be emitted.
945239462Sdim  const DiagnosticBuilder &setForceEmit() const {
946239462Sdim    IsForceEmit = true;
947239462Sdim    return *this;
948239462Sdim  }
949239462Sdim
950239462Sdim  /// \brief Conversion of DiagnosticBuilder to bool always returns \c true.
951239462Sdim  ///
952239462Sdim  /// This allows is to be used in boolean error contexts (where \c true is
953239462Sdim  /// used to indicate that an error has occurred), like:
954239462Sdim  /// \code
955193326Sed  /// return Diag(...);
956239462Sdim  /// \endcode
957193326Sed  operator bool() const { return true; }
958193326Sed
959226633Sdim  void AddString(StringRef S) const {
960234353Sdim    assert(isActive() && "Clients must not add to cleared diagnostic!");
961226633Sdim    assert(NumArgs < DiagnosticsEngine::MaxArguments &&
962193326Sed           "Too many arguments to diagnostic!");
963234353Sdim    DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string;
964234353Sdim    DiagObj->DiagArgumentsStr[NumArgs++] = S;
965193326Sed  }
966198092Srdivacky
967226633Sdim  void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
968234353Sdim    assert(isActive() && "Clients must not add to cleared diagnostic!");
969226633Sdim    assert(NumArgs < DiagnosticsEngine::MaxArguments &&
970193326Sed           "Too many arguments to diagnostic!");
971234353Sdim    DiagObj->DiagArgumentsKind[NumArgs] = Kind;
972234353Sdim    DiagObj->DiagArgumentsVal[NumArgs++] = V;
973193326Sed  }
974198092Srdivacky
975210299Sed  void AddSourceRange(const CharSourceRange &R) const {
976234353Sdim    assert(isActive() && "Clients must not add to cleared diagnostic!");
977234353Sdim    assert(NumRanges < DiagnosticsEngine::MaxRanges &&
978193326Sed           "Too many arguments to diagnostic!");
979234353Sdim    DiagObj->DiagRanges[NumRanges++] = R;
980198092Srdivacky  }
981193326Sed
982206084Srdivacky  void AddFixItHint(const FixItHint &Hint) const {
983234353Sdim    assert(isActive() && "Clients must not add to cleared diagnostic!");
984234353Sdim    assert(NumFixits < DiagnosticsEngine::MaxFixItHints &&
985234353Sdim           "Too many arguments to diagnostic!");
986234353Sdim    DiagObj->DiagFixItHints[NumFixits++] = Hint;
987193326Sed  }
988243830Sdim
989243830Sdim  bool hasMaxRanges() const {
990243830Sdim    return NumRanges == DiagnosticsEngine::MaxRanges;
991243830Sdim  }
992263508Sdim
993263508Sdim  bool hasMaxFixItHints() const {
994263508Sdim    return NumFixits == DiagnosticsEngine::MaxFixItHints;
995263508Sdim  }
996193326Sed};
997193326Sed
998193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
999226633Sdim                                           StringRef S) {
1000193326Sed  DB.AddString(S);
1001193326Sed  return DB;
1002193326Sed}
1003193326Sed
1004193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1005193326Sed                                           const char *Str) {
1006193326Sed  DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
1007226633Sdim                  DiagnosticsEngine::ak_c_string);
1008193326Sed  return DB;
1009193326Sed}
1010193326Sed
1011193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
1012226633Sdim  DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
1013193326Sed  return DB;
1014193326Sed}
1015193326Sed
1016193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
1017226633Sdim  DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
1018193326Sed  return DB;
1019193326Sed}
1020193326Sed
1021193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1022193326Sed                                           unsigned I) {
1023226633Sdim  DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
1024193326Sed  return DB;
1025193326Sed}
1026193326Sed
1027193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1028193326Sed                                           const IdentifierInfo *II) {
1029193326Sed  DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
1030226633Sdim                  DiagnosticsEngine::ak_identifierinfo);
1031193326Sed  return DB;
1032193326Sed}
1033198092Srdivacky
1034198092Srdivacky// Adds a DeclContext to the diagnostic. The enable_if template magic is here
1035198092Srdivacky// so that we only match those arguments that are (statically) DeclContexts;
1036198092Srdivacky// other arguments that derive from DeclContext (e.g., RecordDecls) will not
1037198092Srdivacky// match.
1038198092Srdivackytemplate<typename T>
1039198092Srdivackyinline
1040198092Srdivackytypename llvm::enable_if<llvm::is_same<T, DeclContext>,
1041198092Srdivacky                         const DiagnosticBuilder &>::type
1042198092Srdivackyoperator<<(const DiagnosticBuilder &DB, T *DC) {
1043198092Srdivacky  DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
1044226633Sdim                  DiagnosticsEngine::ak_declcontext);
1045198092Srdivacky  return DB;
1046198092Srdivacky}
1047193326Sed
1048193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1049193326Sed                                           const SourceRange &R) {
1050210299Sed  DB.AddSourceRange(CharSourceRange::getTokenRange(R));
1051193326Sed  return DB;
1052193326Sed}
1053193326Sed
1054193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1055210299Sed                                           const CharSourceRange &R) {
1056210299Sed  DB.AddSourceRange(R);
1057210299Sed  return DB;
1058210299Sed}
1059210299Sed
1060210299Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
1061206084Srdivacky                                           const FixItHint &Hint) {
1062234353Sdim  if (!Hint.isNull())
1063234353Sdim    DB.AddFixItHint(Hint);
1064193326Sed  return DB;
1065193326Sed}
1066193326Sed
1067226633Sdiminline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
1068218893Sdim                                            unsigned DiagID){
1069193326Sed  assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
1070193326Sed  CurDiagLoc = Loc;
1071193326Sed  CurDiagID = DiagID;
1072193326Sed  return DiagnosticBuilder(this);
1073193326Sed}
1074226633Sdiminline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
1075218893Sdim  return Report(SourceLocation(), DiagID);
1076199482Srdivacky}
1077193326Sed
1078193326Sed//===----------------------------------------------------------------------===//
1079226633Sdim// Diagnostic
1080193326Sed//===----------------------------------------------------------------------===//
1081198092Srdivacky
1082239462Sdim/// A little helper class (which is basically a smart pointer that forwards
1083239462Sdim/// info from DiagnosticsEngine) that allows clients to enquire about the
1084239462Sdim/// currently in-flight diagnostic.
1085226633Sdimclass Diagnostic {
1086226633Sdim  const DiagnosticsEngine *DiagObj;
1087226633Sdim  StringRef StoredDiagMessage;
1088193326Sedpublic:
1089226633Sdim  explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {}
1090226633Sdim  Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage)
1091223017Sdim    : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
1092198092Srdivacky
1093226633Sdim  const DiagnosticsEngine *getDiags() const { return DiagObj; }
1094193326Sed  unsigned getID() const { return DiagObj->CurDiagID; }
1095218893Sdim  const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
1096218893Sdim  bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
1097218893Sdim  SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}
1098198092Srdivacky
1099193326Sed  unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
1100198092Srdivacky
1101239462Sdim  /// \brief Return the kind of the specified index.
1102239462Sdim  ///
1103239462Sdim  /// Based on the kind of argument, the accessors below can be used to get
1104239462Sdim  /// the value.
1105239462Sdim  ///
1106239462Sdim  /// \pre Idx < getNumArgs()
1107226633Sdim  DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const {
1108193326Sed    assert(Idx < getNumArgs() && "Argument index out of range!");
1109226633Sdim    return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
1110193326Sed  }
1111198092Srdivacky
1112239462Sdim  /// \brief Return the provided argument string specified by \p Idx.
1113239462Sdim  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string
1114193326Sed  const std::string &getArgStdStr(unsigned Idx) const {
1115226633Sdim    assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
1116193326Sed           "invalid argument accessor!");
1117193326Sed    return DiagObj->DiagArgumentsStr[Idx];
1118193326Sed  }
1119198092Srdivacky
1120239462Sdim  /// \brief Return the specified C string argument.
1121239462Sdim  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string
1122193326Sed  const char *getArgCStr(unsigned Idx) const {
1123226633Sdim    assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
1124193326Sed           "invalid argument accessor!");
1125193326Sed    return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
1126193326Sed  }
1127198092Srdivacky
1128239462Sdim  /// \brief Return the specified signed integer argument.
1129239462Sdim  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint
1130193326Sed  int getArgSInt(unsigned Idx) const {
1131226633Sdim    assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
1132193326Sed           "invalid argument accessor!");
1133193326Sed    return (int)DiagObj->DiagArgumentsVal[Idx];
1134193326Sed  }
1135198092Srdivacky
1136239462Sdim  /// \brief Return the specified unsigned integer argument.
1137239462Sdim  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint
1138193326Sed  unsigned getArgUInt(unsigned Idx) const {
1139226633Sdim    assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
1140193326Sed           "invalid argument accessor!");
1141193326Sed    return (unsigned)DiagObj->DiagArgumentsVal[Idx];
1142193326Sed  }
1143198092Srdivacky
1144239462Sdim  /// \brief Return the specified IdentifierInfo argument.
1145239462Sdim  /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo
1146193326Sed  const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
1147226633Sdim    assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
1148193326Sed           "invalid argument accessor!");
1149193326Sed    return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
1150193326Sed  }
1151198092Srdivacky
1152239462Sdim  /// \brief Return the specified non-string argument in an opaque form.
1153239462Sdim  /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string
1154193326Sed  intptr_t getRawArg(unsigned Idx) const {
1155226633Sdim    assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
1156193326Sed           "invalid argument accessor!");
1157193326Sed    return DiagObj->DiagArgumentsVal[Idx];
1158193326Sed  }
1159198092Srdivacky
1160239462Sdim  /// \brief Return the number of source ranges associated with this diagnostic.
1161193326Sed  unsigned getNumRanges() const {
1162193326Sed    return DiagObj->NumDiagRanges;
1163193326Sed  }
1164198092Srdivacky
1165239462Sdim  /// \pre Idx < getNumRanges()
1166210299Sed  const CharSourceRange &getRange(unsigned Idx) const {
1167193326Sed    assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
1168203955Srdivacky    return DiagObj->DiagRanges[Idx];
1169193326Sed  }
1170198092Srdivacky
1171234353Sdim  /// \brief Return an array reference for this diagnostic's ranges.
1172234353Sdim  ArrayRef<CharSourceRange> getRanges() const {
1173234353Sdim    return llvm::makeArrayRef(DiagObj->DiagRanges, DiagObj->NumDiagRanges);
1174234353Sdim  }
1175234353Sdim
1176206084Srdivacky  unsigned getNumFixItHints() const {
1177234353Sdim    return DiagObj->NumDiagFixItHints;
1178193326Sed  }
1179193326Sed
1180206084Srdivacky  const FixItHint &getFixItHint(unsigned Idx) const {
1181234353Sdim    assert(Idx < getNumFixItHints() && "Invalid index!");
1182234353Sdim    return DiagObj->DiagFixItHints[Idx];
1183193326Sed  }
1184193326Sed
1185206084Srdivacky  const FixItHint *getFixItHints() const {
1186234353Sdim    return getNumFixItHints()? DiagObj->DiagFixItHints : 0;
1187193326Sed  }
1188193326Sed
1189239462Sdim  /// \brief Format this diagnostic into a string, substituting the
1190239462Sdim  /// formal arguments into the %0 slots.
1191239462Sdim  ///
1192239462Sdim  /// The result is appended onto the \p OutStr array.
1193226633Sdim  void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;
1194202379Srdivacky
1195239462Sdim  /// \brief Format the given format-string into the output buffer using the
1196239462Sdim  /// arguments stored in this diagnostic.
1197202379Srdivacky  void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
1198226633Sdim                        SmallVectorImpl<char> &OutStr) const;
1199204643Srdivacky};
1200203955Srdivacky
1201204643Srdivacky/**
1202218893Sdim * \brief Represents a diagnostic in a form that can be retained until its
1203218893Sdim * corresponding source manager is destroyed.
1204204643Srdivacky */
1205204643Srdivackyclass StoredDiagnostic {
1206218893Sdim  unsigned ID;
1207226633Sdim  DiagnosticsEngine::Level Level;
1208204643Srdivacky  FullSourceLoc Loc;
1209204643Srdivacky  std::string Message;
1210210299Sed  std::vector<CharSourceRange> Ranges;
1211206084Srdivacky  std::vector<FixItHint> FixIts;
1212204643Srdivacky
1213204643Srdivackypublic:
1214204643Srdivacky  StoredDiagnostic();
1215226633Sdim  StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
1216226633Sdim  StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1217226633Sdim                   StringRef Message);
1218226633Sdim  StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1219226633Sdim                   StringRef Message, FullSourceLoc Loc,
1220226633Sdim                   ArrayRef<CharSourceRange> Ranges,
1221226633Sdim                   ArrayRef<FixItHint> Fixits);
1222204643Srdivacky  ~StoredDiagnostic();
1223204643Srdivacky
1224204643Srdivacky  /// \brief Evaluates true when this object stores a diagnostic.
1225263508Sdim  LLVM_EXPLICIT operator bool() const { return Message.size() > 0; }
1226204643Srdivacky
1227218893Sdim  unsigned getID() const { return ID; }
1228226633Sdim  DiagnosticsEngine::Level getLevel() const { return Level; }
1229204643Srdivacky  const FullSourceLoc &getLocation() const { return Loc; }
1230226633Sdim  StringRef getMessage() const { return Message; }
1231212904Sdim
1232212904Sdim  void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
1233212904Sdim
1234210299Sed  typedef std::vector<CharSourceRange>::const_iterator range_iterator;
1235204643Srdivacky  range_iterator range_begin() const { return Ranges.begin(); }
1236204643Srdivacky  range_iterator range_end() const { return Ranges.end(); }
1237204643Srdivacky  unsigned range_size() const { return Ranges.size(); }
1238234353Sdim
1239234353Sdim  ArrayRef<CharSourceRange> getRanges() const {
1240234353Sdim    return llvm::makeArrayRef(Ranges);
1241234353Sdim  }
1242204643Srdivacky
1243234353Sdim
1244206084Srdivacky  typedef std::vector<FixItHint>::const_iterator fixit_iterator;
1245204643Srdivacky  fixit_iterator fixit_begin() const { return FixIts.begin(); }
1246204643Srdivacky  fixit_iterator fixit_end() const { return FixIts.end(); }
1247204643Srdivacky  unsigned fixit_size() const { return FixIts.size(); }
1248234353Sdim
1249234353Sdim  ArrayRef<FixItHint> getFixIts() const {
1250234353Sdim    return llvm::makeArrayRef(FixIts);
1251234353Sdim  }
1252193326Sed};
1253198092Srdivacky
1254239462Sdim/// \brief Abstract interface, implemented by clients of the front-end, which
1255239462Sdim/// formats and prints fully processed diagnostics.
1256226633Sdimclass DiagnosticConsumer {
1257218893Sdimprotected:
1258239462Sdim  unsigned NumWarnings;       ///< Number of warnings reported
1259239462Sdim  unsigned NumErrors;         ///< Number of errors reported
1260218893Sdim
1261193326Sedpublic:
1262226633Sdim  DiagnosticConsumer() : NumWarnings(0), NumErrors(0) { }
1263218893Sdim
1264218893Sdim  unsigned getNumErrors() const { return NumErrors; }
1265218893Sdim  unsigned getNumWarnings() const { return NumWarnings; }
1266234353Sdim  virtual void clear() { NumWarnings = NumErrors = 0; }
1267218893Sdim
1268226633Sdim  virtual ~DiagnosticConsumer();
1269198092Srdivacky
1270239462Sdim  /// \brief Callback to inform the diagnostic client that processing
1271198954Srdivacky  /// of a source file is beginning.
1272198954Srdivacky  ///
1273198954Srdivacky  /// Note that diagnostics may be emitted outside the processing of a source
1274198954Srdivacky  /// file, for example during the parsing of command line options. However,
1275198954Srdivacky  /// diagnostics with source range information are required to only be emitted
1276198954Srdivacky  /// in between BeginSourceFile() and EndSourceFile().
1277198954Srdivacky  ///
1278239462Sdim  /// \param LangOpts The language options for the source file being processed.
1279239462Sdim  /// \param PP The preprocessor object being used for the source; this is
1280239462Sdim  /// optional, e.g., it may not be present when processing AST source files.
1281199482Srdivacky  virtual void BeginSourceFile(const LangOptions &LangOpts,
1282199482Srdivacky                               const Preprocessor *PP = 0) {}
1283198092Srdivacky
1284239462Sdim  /// \brief Callback to inform the diagnostic client that processing
1285239462Sdim  /// of a source file has ended.
1286239462Sdim  ///
1287239462Sdim  /// The diagnostic client should assume that any objects made available via
1288239462Sdim  /// BeginSourceFile() are inaccessible.
1289198954Srdivacky  virtual void EndSourceFile() {}
1290198954Srdivacky
1291234353Sdim  /// \brief Callback to inform the diagnostic client that processing of all
1292234353Sdim  /// source files has ended.
1293234353Sdim  virtual void finish() {}
1294234353Sdim
1295239462Sdim  /// \brief Indicates whether the diagnostics handled by this
1296226633Sdim  /// DiagnosticConsumer should be included in the number of diagnostics
1297226633Sdim  /// reported by DiagnosticsEngine.
1298239462Sdim  ///
1299239462Sdim  /// The default implementation returns true.
1300193326Sed  virtual bool IncludeInDiagnosticCounts() const;
1301193326Sed
1302239462Sdim  /// \brief Handle this diagnostic, reporting it to the user or
1303193326Sed  /// capturing it to a log as needed.
1304218893Sdim  ///
1305239462Sdim  /// The default implementation just keeps track of the total number of
1306239462Sdim  /// warnings and errors.
1307226633Sdim  virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1308226633Sdim                                const Diagnostic &Info);
1309193326Sed};
1310193326Sed
1311239462Sdim/// \brief A diagnostic client that ignores all diagnostics.
1312226633Sdimclass IgnoringDiagConsumer : public DiagnosticConsumer {
1313234353Sdim  virtual void anchor();
1314226633Sdim  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1315226633Sdim                        const Diagnostic &Info) {
1316226633Sdim    // Just ignore it.
1317226633Sdim  }
1318226633Sdim};
1319226633Sdim
1320251662Sdim/// \brief Diagnostic consumer that forwards diagnostics along to an
1321251662Sdim/// existing, already-initialized diagnostic consumer.
1322251662Sdim///
1323251662Sdimclass ForwardingDiagnosticConsumer : public DiagnosticConsumer {
1324251662Sdim  DiagnosticConsumer &Target;
1325251662Sdim
1326251662Sdimpublic:
1327251662Sdim  ForwardingDiagnosticConsumer(DiagnosticConsumer &Target) : Target(Target) {}
1328251662Sdim
1329251662Sdim  virtual ~ForwardingDiagnosticConsumer();
1330251662Sdim
1331251662Sdim  virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1332251662Sdim                                const Diagnostic &Info);
1333251662Sdim  virtual void clear();
1334251662Sdim
1335251662Sdim  virtual bool IncludeInDiagnosticCounts() const;
1336251662Sdim};
1337251662Sdim
1338239462Sdim// Struct used for sending info about how a type should be printed.
1339239462Sdimstruct TemplateDiffTypes {
1340239462Sdim  intptr_t FromType;
1341239462Sdim  intptr_t ToType;
1342239462Sdim  unsigned PrintTree : 1;
1343239462Sdim  unsigned PrintFromType : 1;
1344239462Sdim  unsigned ElideType : 1;
1345239462Sdim  unsigned ShowColors : 1;
1346239462Sdim  // The printer sets this variable to true if the template diff was used.
1347239462Sdim  unsigned TemplateDiffUsed : 1;
1348239462Sdim};
1349239462Sdim
1350239462Sdim/// Special character that the diagnostic printer will use to toggle the bold
1351239462Sdim/// attribute.  The character itself will be not be printed.
1352239462Sdimconst char ToggleHighlight = 127;
1353239462Sdim
1354193326Sed}  // end namespace clang
1355193326Sed
1356193326Sed#endif
1357