Diagnostic.h revision 223017
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//===----------------------------------------------------------------------===//
9193326Sed//
10193326Sed//  This file defines the Diagnostic-related interfaces.
11193326Sed//
12193326Sed//===----------------------------------------------------------------------===//
13193326Sed
14193326Sed#ifndef LLVM_CLANG_DIAGNOSTIC_H
15193326Sed#define LLVM_CLANG_DIAGNOSTIC_H
16193326Sed
17218893Sdim#include "clang/Basic/DiagnosticIDs.h"
18193326Sed#include "clang/Basic/SourceLocation.h"
19218893Sdim#include "llvm/ADT/DenseMap.h"
20206275Srdivacky#include "llvm/ADT/IntrusiveRefCntPtr.h"
21212904Sdim#include "llvm/ADT/OwningPtr.h"
22198092Srdivacky#include "llvm/Support/type_traits.h"
23218893Sdim
24198092Srdivacky#include <vector>
25218893Sdim#include <list>
26193326Sed
27193326Sednamespace clang {
28218893Sdim  class DiagnosticClient;
29198092Srdivacky  class DiagnosticBuilder;
30193326Sed  class IdentifierInfo;
31218893Sdim  class DeclContext;
32193326Sed  class LangOptions;
33199482Srdivacky  class Preprocessor;
34218893Sdim  class DiagnosticErrorTrap;
35223017Sdim  class StoredDiagnostic;
36198092Srdivacky
37193326Sed/// \brief Annotates a diagnostic with some code that should be
38193326Sed/// inserted, removed, or replaced to fix the problem.
39193326Sed///
40193326Sed/// This kind of hint should be used when we are certain that the
41193326Sed/// introduction, removal, or modification of a particular (small!)
42193326Sed/// amount of code will correct a compilation error. The compiler
43193326Sed/// should also provide full recovery from such errors, such that
44193326Sed/// suppressing the diagnostic output can still result in successful
45193326Sed/// compilation.
46206084Srdivackyclass FixItHint {
47193326Sedpublic:
48212904Sdim  /// \brief Code that should be replaced to correct the error. Empty for an
49212904Sdim  /// insertion hint.
50210299Sed  CharSourceRange RemoveRange;
51193326Sed
52193326Sed  /// \brief The actual code to insert at the insertion location, as a
53193326Sed  /// string.
54193326Sed  std::string CodeToInsert;
55193326Sed
56193326Sed  /// \brief Empty code modification hint, indicating that no code
57193326Sed  /// modification is known.
58212904Sdim  FixItHint() : RemoveRange() { }
59193326Sed
60199482Srdivacky  bool isNull() const {
61212904Sdim    return !RemoveRange.isValid();
62199482Srdivacky  }
63199482Srdivacky
64193326Sed  /// \brief Create a code modification hint that inserts the given
65193326Sed  /// code string at a specific location.
66206084Srdivacky  static FixItHint CreateInsertion(SourceLocation InsertionLoc,
67206084Srdivacky                                   llvm::StringRef Code) {
68206084Srdivacky    FixItHint Hint;
69212904Sdim    Hint.RemoveRange =
70212904Sdim      CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
71193326Sed    Hint.CodeToInsert = Code;
72193326Sed    return Hint;
73193326Sed  }
74193326Sed
75193326Sed  /// \brief Create a code modification hint that removes the given
76193326Sed  /// source range.
77210299Sed  static FixItHint CreateRemoval(CharSourceRange RemoveRange) {
78206084Srdivacky    FixItHint Hint;
79193326Sed    Hint.RemoveRange = RemoveRange;
80193326Sed    return Hint;
81193326Sed  }
82210299Sed  static FixItHint CreateRemoval(SourceRange RemoveRange) {
83210299Sed    return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange));
84210299Sed  }
85210299Sed
86193326Sed  /// \brief Create a code modification hint that replaces the given
87193326Sed  /// source range with the given code string.
88210299Sed  static FixItHint CreateReplacement(CharSourceRange RemoveRange,
89206084Srdivacky                                     llvm::StringRef Code) {
90206084Srdivacky    FixItHint Hint;
91193326Sed    Hint.RemoveRange = RemoveRange;
92193326Sed    Hint.CodeToInsert = Code;
93193326Sed    return Hint;
94193326Sed  }
95210299Sed
96210299Sed  static FixItHint CreateReplacement(SourceRange RemoveRange,
97210299Sed                                     llvm::StringRef Code) {
98210299Sed    return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
99210299Sed  }
100193326Sed};
101193326Sed
102193326Sed/// Diagnostic - This concrete class is used by the front-end to report
103193326Sed/// problems and issues.  It massages the diagnostics (e.g. handling things like
104193326Sed/// "report warnings as errors" and passes them off to the DiagnosticClient for
105218893Sdim/// reporting to the user. Diagnostic is tied to one translation unit and
106218893Sdim/// one SourceManager.
107206275Srdivackyclass Diagnostic : public llvm::RefCountedBase<Diagnostic> {
108193326Sedpublic:
109193326Sed  /// Level - The level of the diagnostic, after it has been through mapping.
110193326Sed  enum Level {
111218893Sdim    Ignored = DiagnosticIDs::Ignored,
112218893Sdim    Note = DiagnosticIDs::Note,
113218893Sdim    Warning = DiagnosticIDs::Warning,
114218893Sdim    Error = DiagnosticIDs::Error,
115218893Sdim    Fatal = DiagnosticIDs::Fatal
116193326Sed  };
117198092Srdivacky
118193326Sed  /// ExtensionHandling - How do we handle otherwise-unmapped extension?  This
119193326Sed  /// is controlled by -pedantic and -pedantic-errors.
120193326Sed  enum ExtensionHandling {
121193326Sed    Ext_Ignore, Ext_Warn, Ext_Error
122193326Sed  };
123198092Srdivacky
124193326Sed  enum ArgumentKind {
125193326Sed    ak_std_string,      // std::string
126193326Sed    ak_c_string,        // const char *
127193326Sed    ak_sint,            // int
128193326Sed    ak_uint,            // unsigned
129193326Sed    ak_identifierinfo,  // IdentifierInfo
130193326Sed    ak_qualtype,        // QualType
131193326Sed    ak_declarationname, // DeclarationName
132198092Srdivacky    ak_nameddecl,       // NamedDecl *
133198092Srdivacky    ak_nestednamespec,  // NestedNameSpecifier *
134198092Srdivacky    ak_declcontext      // DeclContext *
135193326Sed  };
136210299Sed
137210299Sed  /// Specifies which overload candidates to display when overload resolution
138210299Sed  /// fails.
139210299Sed  enum OverloadsShown {
140210299Sed    Ovl_All,  ///< Show all overloads.
141210299Sed    Ovl_Best  ///< Show just the "best" overload candidates.
142210299Sed  };
143210299Sed
144198398Srdivacky  /// ArgumentValue - This typedef represents on argument value, which is a
145198398Srdivacky  /// union discriminated by ArgumentKind, with a value.
146198398Srdivacky  typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
147193326Sed
148198092Srdivackyprivate:
149193326Sed  unsigned char AllExtensionsSilenced; // Used by __extension__
150193326Sed  bool IgnoreAllWarnings;        // Ignore all warnings: -w
151198092Srdivacky  bool WarningsAsErrors;         // Treat warnings like errors:
152201361Srdivacky  bool ErrorsAsFatal;            // Treat errors like fatal errors.
153193326Sed  bool SuppressSystemWarnings;   // Suppress warnings in system headers.
154198092Srdivacky  bool SuppressAllDiagnostics;   // Suppress all diagnostics.
155210299Sed  OverloadsShown ShowOverloads;  // Which overload candidates to show.
156207619Srdivacky  unsigned ErrorLimit;           // Cap of # errors emitted, 0 -> no limit.
157207619Srdivacky  unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
158207619Srdivacky                                   // 0 -> no limit.
159193326Sed  ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
160218893Sdim  llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags;
161218893Sdim  DiagnosticClient *Client;
162218893Sdim  bool OwnsDiagClient;
163218893Sdim  SourceManager *SourceMgr;
164218893Sdim
165218893Sdim  /// \brief Mapping information for diagnostics.  Mapping info is
166193326Sed  /// packed into four bits per diagnostic.  The low three bits are the mapping
167193326Sed  /// (an instance of diag::Mapping), or zero if unset.  The high bit is set
168193326Sed  /// when the mapping was established as a user mapping.  If the high bit is
169193326Sed  /// clear, then the low bits are set to the default value, and should be
170193326Sed  /// mapped with -pedantic, -Werror, etc.
171218893Sdim  ///
172218893Sdim  /// A new DiagState is created and kept around when diagnostic pragmas modify
173218893Sdim  /// the state so that we know what is the diagnostic state at any given
174218893Sdim  /// source location.
175218893Sdim  class DiagState {
176218893Sdim    llvm::DenseMap<unsigned, unsigned> DiagMap;
177198092Srdivacky
178212904Sdim  public:
179218893Sdim    typedef llvm::DenseMap<unsigned, unsigned>::const_iterator iterator;
180212904Sdim
181218893Sdim    void setMapping(diag::kind Diag, unsigned Map) { DiagMap[Diag] = Map; }
182212904Sdim
183212904Sdim    diag::Mapping getMapping(diag::kind Diag) const {
184218893Sdim      iterator I = DiagMap.find(Diag);
185218893Sdim      if (I != DiagMap.end())
186218893Sdim        return (diag::Mapping)I->second;
187218893Sdim      return diag::Mapping();
188212904Sdim    }
189218893Sdim
190218893Sdim    iterator begin() const { return DiagMap.begin(); }
191218893Sdim    iterator end() const { return DiagMap.end(); }
192212904Sdim  };
193212904Sdim
194218893Sdim  /// \brief Keeps and automatically disposes all DiagStates that we create.
195218893Sdim  std::list<DiagState> DiagStates;
196198092Srdivacky
197218893Sdim  /// \brief Represents a point in source where the diagnostic state was
198218893Sdim  /// modified because of a pragma. 'Loc' can be null if the point represents
199218893Sdim  /// the diagnostic state modifications done through the command-line.
200218893Sdim  struct DiagStatePoint {
201218893Sdim    DiagState *State;
202218893Sdim    FullSourceLoc Loc;
203218893Sdim    DiagStatePoint(DiagState *State, FullSourceLoc Loc)
204218893Sdim      : State(State), Loc(Loc) { }
205218893Sdim
206218893Sdim    bool operator<(const DiagStatePoint &RHS) const {
207218893Sdim      // If Loc is invalid it means it came from <command-line>, in which case
208218893Sdim      // we regard it as coming before any valid source location.
209218893Sdim      if (RHS.Loc.isInvalid())
210218893Sdim        return false;
211218893Sdim      if (Loc.isInvalid())
212218893Sdim        return true;
213218893Sdim      return Loc.isBeforeInTranslationUnitThan(RHS.Loc);
214218893Sdim    }
215218893Sdim  };
216218893Sdim
217218893Sdim  /// \brief A vector of all DiagStatePoints representing changes in diagnostic
218218893Sdim  /// state due to diagnostic pragmas. The vector is always sorted according to
219218893Sdim  /// the SourceLocation of the DiagStatePoint.
220218893Sdim  typedef std::vector<DiagStatePoint> DiagStatePointsTy;
221218893Sdim  mutable DiagStatePointsTy DiagStatePoints;
222218893Sdim
223218893Sdim  /// \brief Keeps the DiagState that was active during each diagnostic 'push'
224218893Sdim  /// so we can get back at it when we 'pop'.
225218893Sdim  std::vector<DiagState *> DiagStateOnPushStack;
226218893Sdim
227218893Sdim  DiagState *GetCurDiagState() const {
228218893Sdim    assert(!DiagStatePoints.empty());
229218893Sdim    return DiagStatePoints.back().State;
230218893Sdim  }
231218893Sdim
232218893Sdim  void PushDiagStatePoint(DiagState *State, SourceLocation L) {
233218893Sdim    FullSourceLoc Loc(L, *SourceMgr);
234218893Sdim    // Make sure that DiagStatePoints is always sorted according to Loc.
235218893Sdim    assert((Loc.isValid() || DiagStatePoints.empty()) &&
236218893Sdim           "Adding invalid loc point after another point");
237218893Sdim    assert((Loc.isInvalid() || DiagStatePoints.empty() ||
238218893Sdim            DiagStatePoints.back().Loc.isInvalid() ||
239218893Sdim            DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) &&
240218893Sdim           "Previous point loc comes after or is the same as new one");
241218893Sdim    DiagStatePoints.push_back(DiagStatePoint(State,
242218893Sdim                                             FullSourceLoc(Loc, *SourceMgr)));
243218893Sdim  }
244218893Sdim
245218893Sdim  /// \brief Finds the DiagStatePoint that contains the diagnostic state of
246218893Sdim  /// the given source location.
247218893Sdim  DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
248218893Sdim
249193326Sed  /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
250193326Sed  /// fatal error is emitted, and is sticky.
251193326Sed  bool ErrorOccurred;
252193326Sed  bool FatalErrorOccurred;
253198092Srdivacky
254193326Sed  /// LastDiagLevel - This is the level of the last diagnostic emitted.  This is
255193326Sed  /// used to emit continuation diagnostics with the same level as the
256193326Sed  /// diagnostic that they follow.
257218893Sdim  DiagnosticIDs::Level LastDiagLevel;
258193326Sed
259207619Srdivacky  unsigned NumWarnings;       // Number of warnings reported
260207619Srdivacky  unsigned NumErrors;         // Number of errors reported
261207619Srdivacky  unsigned NumErrorsSuppressed; // Number of errors suppressed
262193326Sed
263193326Sed  /// ArgToStringFn - A function pointer that converts an opaque diagnostic
264193326Sed  /// argument to a strings.  This takes the modifiers and argument that was
265193326Sed  /// present in the diagnostic.
266198398Srdivacky  ///
267198398Srdivacky  /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
268198398Srdivacky  /// arguments formatted for this diagnostic.  Implementations of this function
269198398Srdivacky  /// can use this information to avoid redundancy across arguments.
270198398Srdivacky  ///
271193326Sed  /// This is a hack to avoid a layering violation between libbasic and libsema.
272193326Sed  typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val,
273193326Sed                                  const char *Modifier, unsigned ModifierLen,
274193326Sed                                  const char *Argument, unsigned ArgumentLen,
275198398Srdivacky                                  const ArgumentValue *PrevArgs,
276198398Srdivacky                                  unsigned NumPrevArgs,
277193326Sed                                  llvm::SmallVectorImpl<char> &Output,
278193326Sed                                  void *Cookie);
279193326Sed  void *ArgToStringCookie;
280193326Sed  ArgToStringFnTy ArgToStringFn;
281206084Srdivacky
282206084Srdivacky  /// \brief ID of the "delayed" diagnostic, which is a (typically
283206084Srdivacky  /// fatal) diagnostic that had to be delayed because it was found
284206084Srdivacky  /// while emitting another diagnostic.
285206084Srdivacky  unsigned DelayedDiagID;
286206084Srdivacky
287206084Srdivacky  /// \brief First string argument for the delayed diagnostic.
288206084Srdivacky  std::string DelayedDiagArg1;
289206084Srdivacky
290206084Srdivacky  /// \brief Second string argument for the delayed diagnostic.
291206084Srdivacky  std::string DelayedDiagArg2;
292206084Srdivacky
293193326Sedpublic:
294218893Sdim  explicit Diagnostic(const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
295218893Sdim                      DiagnosticClient *client = 0,
296218893Sdim                      bool ShouldOwnClient = true);
297193326Sed  ~Diagnostic();
298198092Srdivacky
299218893Sdim  const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
300218893Sdim    return Diags;
301218893Sdim  }
302218893Sdim
303218893Sdim  DiagnosticClient *getClient() { return Client; }
304218893Sdim  const DiagnosticClient *getClient() const { return Client; }
305218893Sdim
306218893Sdim  /// \brief Return the current diagnostic client along with ownership of that
307218893Sdim  /// client.
308218893Sdim  DiagnosticClient *takeClient() {
309218893Sdim    OwnsDiagClient = false;
310218893Sdim    return Client;
311218893Sdim  }
312218893Sdim
313218893Sdim  bool hasSourceManager() const { return SourceMgr != 0; }
314218893Sdim  SourceManager &getSourceManager() const {
315218893Sdim    assert(SourceMgr && "SourceManager not set!");
316218893Sdim    return *SourceMgr;
317218893Sdim  }
318218893Sdim  void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
319218893Sdim
320193326Sed  //===--------------------------------------------------------------------===//
321193326Sed  //  Diagnostic characterization methods, used by a client to customize how
322218893Sdim  //  diagnostics are emitted.
323193326Sed  //
324198092Srdivacky
325198092Srdivacky  /// pushMappings - Copies the current DiagMappings and pushes the new copy
326198092Srdivacky  /// onto the top of the stack.
327218893Sdim  void pushMappings(SourceLocation Loc);
328198092Srdivacky
329198092Srdivacky  /// popMappings - Pops the current DiagMappings off the top of the stack
330198092Srdivacky  /// causing the new top of the stack to be the active mappings. Returns
331198092Srdivacky  /// true if the pop happens, false if there is only one DiagMapping on the
332198092Srdivacky  /// stack.
333218893Sdim  bool popMappings(SourceLocation Loc);
334198092Srdivacky
335212904Sdim  /// \brief Set the diagnostic client associated with this diagnostic object.
336212904Sdim  ///
337218893Sdim  /// \param ShouldOwnClient true if the diagnostic object should take
338218893Sdim  /// ownership of \c client.
339218893Sdim  void setClient(DiagnosticClient *client, bool ShouldOwnClient = true);
340193326Sed
341207619Srdivacky  /// setErrorLimit - Specify a limit for the number of errors we should
342207619Srdivacky  /// emit before giving up.  Zero disables the limit.
343207619Srdivacky  void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }
344207619Srdivacky
345207619Srdivacky  /// \brief Specify the maximum number of template instantiation
346207619Srdivacky  /// notes to emit along with a given diagnostic.
347207619Srdivacky  void setTemplateBacktraceLimit(unsigned Limit) {
348207619Srdivacky    TemplateBacktraceLimit = Limit;
349207619Srdivacky  }
350207632Srdivacky
351207619Srdivacky  /// \brief Retrieve the maximum number of template instantiation
352207619Srdivacky  /// nodes to emit along with a given diagnostic.
353207619Srdivacky  unsigned getTemplateBacktraceLimit() const {
354207619Srdivacky    return TemplateBacktraceLimit;
355207619Srdivacky  }
356207632Srdivacky
357193326Sed  /// setIgnoreAllWarnings - When set to true, any unmapped warnings are
358193326Sed  /// ignored.  If this and WarningsAsErrors are both set, then this one wins.
359193326Sed  void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
360193326Sed  bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
361198092Srdivacky
362193326Sed  /// setWarningsAsErrors - When set to true, any warnings reported are issued
363193326Sed  /// as errors.
364193326Sed  void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
365193326Sed  bool getWarningsAsErrors() const { return WarningsAsErrors; }
366198092Srdivacky
367201361Srdivacky  /// setErrorsAsFatal - When set to true, any error reported is made a
368201361Srdivacky  /// fatal error.
369201361Srdivacky  void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
370201361Srdivacky  bool getErrorsAsFatal() const { return ErrorsAsFatal; }
371201361Srdivacky
372193326Sed  /// setSuppressSystemWarnings - When set to true mask warnings that
373193326Sed  /// come from system headers.
374193326Sed  void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
375193326Sed  bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
376193326Sed
377198092Srdivacky  /// \brief Suppress all diagnostics, to silence the front end when we
378198092Srdivacky  /// know that we don't want any more diagnostics to be passed along to the
379198092Srdivacky  /// client
380198092Srdivacky  void setSuppressAllDiagnostics(bool Val = true) {
381198092Srdivacky    SuppressAllDiagnostics = Val;
382198092Srdivacky  }
383198092Srdivacky  bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
384198092Srdivacky
385210299Sed  /// \brief Specify which overload candidates to show when overload resolution
386210299Sed  /// fails.  By default, we show all candidates.
387210299Sed  void setShowOverloads(OverloadsShown Val) {
388210299Sed    ShowOverloads = Val;
389210299Sed  }
390210299Sed  OverloadsShown getShowOverloads() const { return ShowOverloads; }
391210299Sed
392198092Srdivacky  /// \brief Pretend that the last diagnostic issued was ignored. This can
393198092Srdivacky  /// be used by clients who suppress diagnostics themselves.
394198092Srdivacky  void setLastDiagnosticIgnored() {
395218893Sdim    LastDiagLevel = DiagnosticIDs::Ignored;
396198092Srdivacky  }
397198092Srdivacky
398193326Sed  /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
399193326Sed  /// extension diagnostics are mapped onto ignore/warning/error.  This
400193326Sed  /// corresponds to the GCC -pedantic and -pedantic-errors option.
401193326Sed  void setExtensionHandlingBehavior(ExtensionHandling H) {
402193326Sed    ExtBehavior = H;
403193326Sed  }
404223017Sdim  ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; }
405198092Srdivacky
406193326Sed  /// AllExtensionsSilenced - This is a counter bumped when an __extension__
407193326Sed  /// block is encountered.  When non-zero, all extension diagnostics are
408193326Sed  /// entirely silenced, no matter how they are mapped.
409193326Sed  void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
410193326Sed  void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
411198092Srdivacky  bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
412198092Srdivacky
413218893Sdim  /// \brief This allows the client to specify that certain
414193326Sed  /// warnings are ignored.  Notes can never be mapped, errors can only be
415193326Sed  /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
416218893Sdim  ///
417218893Sdim  /// \param Loc The source location that this change of diagnostic state should
418218893Sdim  /// take affect. It can be null if we are setting the latest state.
419218893Sdim  void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
420218893Sdim                            SourceLocation Loc);
421198092Srdivacky
422193326Sed  /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
423193326Sed  /// "unknown-pragmas" to have the specified mapping.  This returns true and
424193326Sed  /// ignores the request if "Group" was unknown, false otherwise.
425218893Sdim  ///
426218893Sdim  /// 'Loc' is the source location that this change of diagnostic state should
427218893Sdim  /// take affect. It can be null if we are setting the state from command-line.
428223017Sdim  bool setDiagnosticGroupMapping(llvm::StringRef Group, diag::Mapping Map,
429218893Sdim                                 SourceLocation Loc = SourceLocation()) {
430218893Sdim    return Diags->setDiagnosticGroupMapping(Group, Map, Loc, *this);
431218893Sdim  }
432193326Sed
433193326Sed  bool hasErrorOccurred() const { return ErrorOccurred; }
434193326Sed  bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
435193326Sed
436207619Srdivacky  unsigned getNumWarnings() const { return NumWarnings; }
437198092Srdivacky
438212904Sdim  void setNumWarnings(unsigned NumWarnings) {
439212904Sdim    this->NumWarnings = NumWarnings;
440212904Sdim  }
441212904Sdim
442193326Sed  /// getCustomDiagID - Return an ID for a diagnostic with the specified message
443193326Sed  /// and level.  If this is the first request for this diagnosic, it is
444193326Sed  /// registered and created, otherwise the existing ID is returned.
445218893Sdim  unsigned getCustomDiagID(Level L, llvm::StringRef Message) {
446218893Sdim    return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
447218893Sdim  }
448198092Srdivacky
449193326Sed  /// ConvertArgToString - This method converts a diagnostic argument (as an
450193326Sed  /// intptr_t) into the string that represents it.
451193326Sed  void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
452193326Sed                          const char *Modifier, unsigned ModLen,
453193326Sed                          const char *Argument, unsigned ArgLen,
454198398Srdivacky                          const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
455193326Sed                          llvm::SmallVectorImpl<char> &Output) const {
456198398Srdivacky    ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
457198398Srdivacky                  PrevArgs, NumPrevArgs, Output, ArgToStringCookie);
458193326Sed  }
459198092Srdivacky
460193326Sed  void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
461193326Sed    ArgToStringFn = Fn;
462193326Sed    ArgToStringCookie = Cookie;
463193326Sed  }
464198092Srdivacky
465212904Sdim  /// \brief Reset the state of the diagnostic object to its initial
466212904Sdim  /// configuration.
467212904Sdim  void Reset();
468212904Sdim
469193326Sed  //===--------------------------------------------------------------------===//
470193326Sed  // Diagnostic classification and reporting interfaces.
471193326Sed  //
472193326Sed
473218893Sdim  /// \brief Based on the way the client configured the Diagnostic
474218893Sdim  /// object, classify the specified diagnostic ID into a Level, consumable by
475218893Sdim  /// the DiagnosticClient.
476193326Sed  ///
477218893Sdim  /// \param Loc The source location we are interested in finding out the
478218893Sdim  /// diagnostic state. Can be null in order to query the latest state.
479219077Sdim  Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc,
480219077Sdim                           diag::Mapping *mapping = 0) const {
481219077Sdim    return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this, mapping);
482207619Srdivacky  }
483198092Srdivacky
484193326Sed  /// Report - Issue the message to the client.  @c DiagID is a member of the
485193326Sed  /// @c diag::kind enum.  This actually returns aninstance of DiagnosticBuilder
486193326Sed  /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed.
487193326Sed  /// @c Pos represents the source location associated with the diagnostic,
488193326Sed  /// which can be an invalid location if no position information is available.
489218893Sdim  inline DiagnosticBuilder Report(SourceLocation Pos, unsigned DiagID);
490199482Srdivacky  inline DiagnosticBuilder Report(unsigned DiagID);
491193326Sed
492223017Sdim  void Report(const StoredDiagnostic &storedDiag);
493223017Sdim
494206084Srdivacky  /// \brief Determine whethere there is already a diagnostic in flight.
495206084Srdivacky  bool isDiagnosticInFlight() const { return CurDiagID != ~0U; }
496206084Srdivacky
497206084Srdivacky  /// \brief Set the "delayed" diagnostic that will be emitted once
498206084Srdivacky  /// the current diagnostic completes.
499206084Srdivacky  ///
500206084Srdivacky  ///  If a diagnostic is already in-flight but the front end must
501206084Srdivacky  ///  report a problem (e.g., with an inconsistent file system
502206084Srdivacky  ///  state), this routine sets a "delayed" diagnostic that will be
503206084Srdivacky  ///  emitted after the current diagnostic completes. This should
504206084Srdivacky  ///  only be used for fatal errors detected at inconvenient
505206084Srdivacky  ///  times. If emitting a delayed diagnostic causes a second delayed
506206084Srdivacky  ///  diagnostic to be introduced, that second delayed diagnostic
507206084Srdivacky  ///  will be ignored.
508206084Srdivacky  ///
509206084Srdivacky  /// \param DiagID The ID of the diagnostic being delayed.
510206084Srdivacky  ///
511206084Srdivacky  /// \param Arg1 A string argument that will be provided to the
512206084Srdivacky  /// diagnostic. A copy of this string will be stored in the
513206084Srdivacky  /// Diagnostic object itself.
514206084Srdivacky  ///
515206084Srdivacky  /// \param Arg2 A string argument that will be provided to the
516206084Srdivacky  /// diagnostic. A copy of this string will be stored in the
517206084Srdivacky  /// Diagnostic object itself.
518206084Srdivacky  void SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1 = "",
519206084Srdivacky                            llvm::StringRef Arg2 = "");
520206084Srdivacky
521193326Sed  /// \brief Clear out the current diagnostic.
522193326Sed  void Clear() { CurDiagID = ~0U; }
523198092Srdivacky
524193326Sedprivate:
525206084Srdivacky  /// \brief Report the delayed diagnostic.
526206084Srdivacky  void ReportDelayed();
527206084Srdivacky
528206084Srdivacky
529193326Sed  /// getDiagnosticMappingInfo - Return the mapping info currently set for the
530193326Sed  /// specified builtin diagnostic.  This returns the high bit encoding, or zero
531193326Sed  /// if the field is completely uninitialized.
532218893Sdim  diag::Mapping getDiagnosticMappingInfo(diag::kind Diag,
533218893Sdim                                         DiagState *State) const {
534218893Sdim    return State->getMapping(Diag);
535193326Sed  }
536198092Srdivacky
537193326Sed  void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map,
538218893Sdim                                    DiagState *State,
539218893Sdim                                    bool isUser, bool isPragma) const {
540193326Sed    if (isUser) Map |= 8;  // Set the high bit for user mappings.
541218893Sdim    if (isPragma) Map |= 0x10;  // Set the bit for diagnostic pragma mappings.
542218893Sdim    State->setMapping((diag::kind)DiagId, Map);
543193326Sed  }
544198092Srdivacky
545193326Sed  // This is private state used by DiagnosticBuilder.  We put it here instead of
546193326Sed  // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
547193326Sed  // object.  This implementation choice means that we can only have one
548193326Sed  // diagnostic "in flight" at a time, but this seems to be a reasonable
549193326Sed  // tradeoff to keep these objects small.  Assertions verify that only one
550193326Sed  // diagnostic is in flight at a time.
551218893Sdim  friend class DiagnosticIDs;
552193326Sed  friend class DiagnosticBuilder;
553193326Sed  friend class DiagnosticInfo;
554218893Sdim  friend class PartialDiagnostic;
555218893Sdim  friend class DiagnosticErrorTrap;
556218893Sdim
557193326Sed  /// CurDiagLoc - This is the location of the current diagnostic that is in
558193326Sed  /// flight.
559218893Sdim  SourceLocation CurDiagLoc;
560198092Srdivacky
561193326Sed  /// CurDiagID - This is the ID of the current diagnostic that is in flight.
562193326Sed  /// This is set to ~0U when there is no diagnostic in flight.
563193326Sed  unsigned CurDiagID;
564193326Sed
565193326Sed  enum {
566193326Sed    /// MaxArguments - The maximum number of arguments we can hold. We currently
567193326Sed    /// only support up to 10 arguments (%0-%9).  A single diagnostic with more
568193326Sed    /// than that almost certainly has to be simplified anyway.
569193326Sed    MaxArguments = 10
570193326Sed  };
571198092Srdivacky
572193326Sed  /// NumDiagArgs - This contains the number of entries in Arguments.
573193326Sed  signed char NumDiagArgs;
574193326Sed  /// NumRanges - This is the number of ranges in the DiagRanges array.
575193326Sed  unsigned char NumDiagRanges;
576193326Sed  /// \brief The number of code modifications hints in the
577206084Srdivacky  /// FixItHints array.
578206084Srdivacky  unsigned char NumFixItHints;
579193326Sed
580193326Sed  /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
581193326Sed  /// values, with one for each argument.  This specifies whether the argument
582193326Sed  /// is in DiagArgumentsStr or in DiagArguments.
583193326Sed  unsigned char DiagArgumentsKind[MaxArguments];
584198092Srdivacky
585193326Sed  /// DiagArgumentsStr - This holds the values of each string argument for the
586193326Sed  /// current diagnostic.  This value is only used when the corresponding
587193326Sed  /// ArgumentKind is ak_std_string.
588193326Sed  std::string DiagArgumentsStr[MaxArguments];
589193326Sed
590193326Sed  /// DiagArgumentsVal - The values for the various substitution positions. This
591193326Sed  /// is used when the argument is not an std::string.  The specific value is
592221345Sdim  /// mangled into an intptr_t and the interpretation depends on exactly what
593193326Sed  /// sort of argument kind it is.
594193326Sed  intptr_t DiagArgumentsVal[MaxArguments];
595198092Srdivacky
596193326Sed  /// DiagRanges - The list of ranges added to this diagnostic.  It currently
597193326Sed  /// only support 10 ranges, could easily be extended if needed.
598210299Sed  CharSourceRange DiagRanges[10];
599198092Srdivacky
600206084Srdivacky  enum { MaxFixItHints = 3 };
601193326Sed
602206084Srdivacky  /// FixItHints - If valid, provides a hint with some code
603193326Sed  /// to insert, remove, or modify at a particular position.
604206084Srdivacky  FixItHint FixItHints[MaxFixItHints];
605193326Sed
606193326Sed  /// ProcessDiag - This is the method used to report a diagnostic that is
607193326Sed  /// finally fully formed.
608194179Sed  ///
609194179Sed  /// \returns true if the diagnostic was emitted, false if it was
610194179Sed  /// suppressed.
611218893Sdim  bool ProcessDiag() {
612218893Sdim    return Diags->ProcessDiag(*this);
613218893Sdim  }
614218893Sdim
615218893Sdim  friend class ASTReader;
616218893Sdim  friend class ASTWriter;
617193326Sed};
618193326Sed
619218893Sdim/// \brief RAII class that determines when any errors have occurred
620218893Sdim/// between the time the instance was created and the time it was
621218893Sdim/// queried.
622218893Sdimclass DiagnosticErrorTrap {
623218893Sdim  Diagnostic &Diag;
624218893Sdim  unsigned PrevErrors;
625218893Sdim
626218893Sdimpublic:
627218893Sdim  explicit DiagnosticErrorTrap(Diagnostic &Diag)
628218893Sdim    : Diag(Diag), PrevErrors(Diag.NumErrors) {}
629218893Sdim
630218893Sdim  /// \brief Determine whether any errors have occurred since this
631218893Sdim  /// object instance was created.
632218893Sdim  bool hasErrorOccurred() const {
633218893Sdim    return Diag.NumErrors > PrevErrors;
634218893Sdim  }
635218893Sdim
636218893Sdim  // Set to initial state of "no errors occurred".
637218893Sdim  void reset() { PrevErrors = Diag.NumErrors; }
638218893Sdim};
639218893Sdim
640193326Sed//===----------------------------------------------------------------------===//
641193326Sed// DiagnosticBuilder
642193326Sed//===----------------------------------------------------------------------===//
643193326Sed
644193326Sed/// DiagnosticBuilder - This is a little helper class used to produce
645193326Sed/// diagnostics.  This is constructed by the Diagnostic::Report method, and
646193326Sed/// allows insertion of extra information (arguments and source ranges) into the
647193326Sed/// currently "in flight" diagnostic.  When the temporary for the builder is
648193326Sed/// destroyed, the diagnostic is issued.
649193326Sed///
650193326Sed/// Note that many of these will be created as temporary objects (many call
651193326Sed/// sites), so we want them to be small and we never want their address taken.
652193326Sed/// This ensures that compilers with somewhat reasonable optimizers will promote
653193326Sed/// the common fields to registers, eliminating increments of the NumArgs field,
654193326Sed/// for example.
655193326Sedclass DiagnosticBuilder {
656193326Sed  mutable Diagnostic *DiagObj;
657206084Srdivacky  mutable unsigned NumArgs, NumRanges, NumFixItHints;
658198092Srdivacky
659193326Sed  void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
660193326Sed  friend class Diagnostic;
661193326Sed  explicit DiagnosticBuilder(Diagnostic *diagObj)
662206084Srdivacky    : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {}
663193326Sed
664218893Sdim  friend class PartialDiagnostic;
665218893Sdim
666218893Sdimprotected:
667218893Sdim  void FlushCounts();
668218893Sdim
669198092Srdivackypublic:
670193326Sed  /// Copy constructor.  When copied, this "takes" the diagnostic info from the
671193326Sed  /// input and neuters it.
672193326Sed  DiagnosticBuilder(const DiagnosticBuilder &D) {
673193326Sed    DiagObj = D.DiagObj;
674193326Sed    D.DiagObj = 0;
675193326Sed    NumArgs = D.NumArgs;
676193326Sed    NumRanges = D.NumRanges;
677206084Srdivacky    NumFixItHints = D.NumFixItHints;
678193326Sed  }
679193326Sed
680194179Sed  /// \brief Simple enumeration value used to give a name to the
681194179Sed  /// suppress-diagnostic constructor.
682194179Sed  enum SuppressKind { Suppress };
683194179Sed
684194179Sed  /// \brief Create an empty DiagnosticBuilder object that represents
685194179Sed  /// no actual diagnostic.
686198092Srdivacky  explicit DiagnosticBuilder(SuppressKind)
687206084Srdivacky    : DiagObj(0), NumArgs(0), NumRanges(0), NumFixItHints(0) { }
688194179Sed
689193326Sed  /// \brief Force the diagnostic builder to emit the diagnostic now.
690193326Sed  ///
691193326Sed  /// Once this function has been called, the DiagnosticBuilder object
692193326Sed  /// should not be used again before it is destroyed.
693194179Sed  ///
694194179Sed  /// \returns true if a diagnostic was emitted, false if the
695194179Sed  /// diagnostic was suppressed.
696206084Srdivacky  bool Emit();
697193326Sed
698193326Sed  /// Destructor - The dtor emits the diagnostic if it hasn't already
699193326Sed  /// been emitted.
700193326Sed  ~DiagnosticBuilder() { Emit(); }
701198092Srdivacky
702203955Srdivacky  /// isActive - Determine whether this diagnostic is still active.
703203955Srdivacky  bool isActive() const { return DiagObj != 0; }
704203955Srdivacky
705218893Sdim  /// \brief Retrieve the active diagnostic ID.
706218893Sdim  ///
707218893Sdim  /// \pre \c isActive()
708218893Sdim  unsigned getDiagID() const {
709218893Sdim    assert(isActive() && "Diagnostic is inactive");
710218893Sdim    return DiagObj->CurDiagID;
711218893Sdim  }
712218893Sdim
713218893Sdim  /// \brief Clear out the current diagnostic.
714218893Sdim  void Clear() { DiagObj = 0; }
715218893Sdim
716193326Sed  /// Operator bool: conversion of DiagnosticBuilder to bool always returns
717193326Sed  /// true.  This allows is to be used in boolean error contexts like:
718193326Sed  /// return Diag(...);
719193326Sed  operator bool() const { return true; }
720193326Sed
721198398Srdivacky  void AddString(llvm::StringRef S) const {
722193326Sed    assert(NumArgs < Diagnostic::MaxArguments &&
723193326Sed           "Too many arguments to diagnostic!");
724194179Sed    if (DiagObj) {
725194179Sed      DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string;
726194179Sed      DiagObj->DiagArgumentsStr[NumArgs++] = S;
727194179Sed    }
728193326Sed  }
729198092Srdivacky
730193326Sed  void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const {
731193326Sed    assert(NumArgs < Diagnostic::MaxArguments &&
732193326Sed           "Too many arguments to diagnostic!");
733194179Sed    if (DiagObj) {
734194179Sed      DiagObj->DiagArgumentsKind[NumArgs] = Kind;
735194179Sed      DiagObj->DiagArgumentsVal[NumArgs++] = V;
736194179Sed    }
737193326Sed  }
738198092Srdivacky
739210299Sed  void AddSourceRange(const CharSourceRange &R) const {
740198092Srdivacky    assert(NumRanges <
741193326Sed           sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
742193326Sed           "Too many arguments to diagnostic!");
743194179Sed    if (DiagObj)
744203955Srdivacky      DiagObj->DiagRanges[NumRanges++] = R;
745198092Srdivacky  }
746193326Sed
747206084Srdivacky  void AddFixItHint(const FixItHint &Hint) const {
748206084Srdivacky    assert(NumFixItHints < Diagnostic::MaxFixItHints &&
749206084Srdivacky           "Too many fix-it hints!");
750194179Sed    if (DiagObj)
751206084Srdivacky      DiagObj->FixItHints[NumFixItHints++] = Hint;
752193326Sed  }
753193326Sed};
754193326Sed
755193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
756198398Srdivacky                                           llvm::StringRef S) {
757193326Sed  DB.AddString(S);
758193326Sed  return DB;
759193326Sed}
760193326Sed
761193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
762193326Sed                                           const char *Str) {
763193326Sed  DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
764193326Sed                  Diagnostic::ak_c_string);
765193326Sed  return DB;
766193326Sed}
767193326Sed
768193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
769193326Sed  DB.AddTaggedVal(I, Diagnostic::ak_sint);
770193326Sed  return DB;
771193326Sed}
772193326Sed
773193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
774193326Sed  DB.AddTaggedVal(I, Diagnostic::ak_sint);
775193326Sed  return DB;
776193326Sed}
777193326Sed
778193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
779193326Sed                                           unsigned I) {
780193326Sed  DB.AddTaggedVal(I, Diagnostic::ak_uint);
781193326Sed  return DB;
782193326Sed}
783193326Sed
784193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
785193326Sed                                           const IdentifierInfo *II) {
786193326Sed  DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
787193326Sed                  Diagnostic::ak_identifierinfo);
788193326Sed  return DB;
789193326Sed}
790198092Srdivacky
791198092Srdivacky// Adds a DeclContext to the diagnostic. The enable_if template magic is here
792198092Srdivacky// so that we only match those arguments that are (statically) DeclContexts;
793198092Srdivacky// other arguments that derive from DeclContext (e.g., RecordDecls) will not
794198092Srdivacky// match.
795198092Srdivackytemplate<typename T>
796198092Srdivackyinline
797198092Srdivackytypename llvm::enable_if<llvm::is_same<T, DeclContext>,
798198092Srdivacky                         const DiagnosticBuilder &>::type
799198092Srdivackyoperator<<(const DiagnosticBuilder &DB, T *DC) {
800198092Srdivacky  DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
801198092Srdivacky                  Diagnostic::ak_declcontext);
802198092Srdivacky  return DB;
803198092Srdivacky}
804193326Sed
805193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
806193326Sed                                           const SourceRange &R) {
807210299Sed  DB.AddSourceRange(CharSourceRange::getTokenRange(R));
808193326Sed  return DB;
809193326Sed}
810193326Sed
811193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
812210299Sed                                           const CharSourceRange &R) {
813210299Sed  DB.AddSourceRange(R);
814210299Sed  return DB;
815210299Sed}
816210299Sed
817210299Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
818206084Srdivacky                                           const FixItHint &Hint) {
819206084Srdivacky  DB.AddFixItHint(Hint);
820193326Sed  return DB;
821193326Sed}
822193326Sed
823193326Sed/// Report - Issue the message to the client.  DiagID is a member of the
824193326Sed/// diag::kind enum.  This actually returns a new instance of DiagnosticBuilder
825193326Sed/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
826218893Sdiminline DiagnosticBuilder Diagnostic::Report(SourceLocation Loc,
827218893Sdim                                            unsigned DiagID){
828193326Sed  assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
829193326Sed  CurDiagLoc = Loc;
830193326Sed  CurDiagID = DiagID;
831193326Sed  return DiagnosticBuilder(this);
832193326Sed}
833199482Srdivackyinline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) {
834218893Sdim  return Report(SourceLocation(), DiagID);
835199482Srdivacky}
836193326Sed
837193326Sed//===----------------------------------------------------------------------===//
838193326Sed// DiagnosticInfo
839193326Sed//===----------------------------------------------------------------------===//
840198092Srdivacky
841193326Sed/// DiagnosticInfo - This is a little helper class (which is basically a smart
842193326Sed/// pointer that forward info from Diagnostic) that allows clients to enquire
843193326Sed/// about the currently in-flight diagnostic.
844193326Sedclass DiagnosticInfo {
845193326Sed  const Diagnostic *DiagObj;
846223017Sdim  llvm::StringRef StoredDiagMessage;
847193326Sedpublic:
848193326Sed  explicit DiagnosticInfo(const Diagnostic *DO) : DiagObj(DO) {}
849223017Sdim  DiagnosticInfo(const Diagnostic *DO, llvm::StringRef storedDiagMessage)
850223017Sdim    : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
851198092Srdivacky
852193326Sed  const Diagnostic *getDiags() const { return DiagObj; }
853193326Sed  unsigned getID() const { return DiagObj->CurDiagID; }
854218893Sdim  const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
855218893Sdim  bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
856218893Sdim  SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}
857198092Srdivacky
858193326Sed  unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
859198092Srdivacky
860193326Sed  /// getArgKind - Return the kind of the specified index.  Based on the kind
861193326Sed  /// of argument, the accessors below can be used to get the value.
862193326Sed  Diagnostic::ArgumentKind getArgKind(unsigned Idx) const {
863193326Sed    assert(Idx < getNumArgs() && "Argument index out of range!");
864193326Sed    return (Diagnostic::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
865193326Sed  }
866198092Srdivacky
867193326Sed  /// getArgStdStr - Return the provided argument string specified by Idx.
868193326Sed  const std::string &getArgStdStr(unsigned Idx) const {
869193326Sed    assert(getArgKind(Idx) == Diagnostic::ak_std_string &&
870193326Sed           "invalid argument accessor!");
871193326Sed    return DiagObj->DiagArgumentsStr[Idx];
872193326Sed  }
873198092Srdivacky
874193326Sed  /// getArgCStr - Return the specified C string argument.
875193326Sed  const char *getArgCStr(unsigned Idx) const {
876193326Sed    assert(getArgKind(Idx) == Diagnostic::ak_c_string &&
877193326Sed           "invalid argument accessor!");
878193326Sed    return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
879193326Sed  }
880198092Srdivacky
881193326Sed  /// getArgSInt - Return the specified signed integer argument.
882193326Sed  int getArgSInt(unsigned Idx) const {
883193326Sed    assert(getArgKind(Idx) == Diagnostic::ak_sint &&
884193326Sed           "invalid argument accessor!");
885193326Sed    return (int)DiagObj->DiagArgumentsVal[Idx];
886193326Sed  }
887198092Srdivacky
888193326Sed  /// getArgUInt - Return the specified unsigned integer argument.
889193326Sed  unsigned getArgUInt(unsigned Idx) const {
890193326Sed    assert(getArgKind(Idx) == Diagnostic::ak_uint &&
891193326Sed           "invalid argument accessor!");
892193326Sed    return (unsigned)DiagObj->DiagArgumentsVal[Idx];
893193326Sed  }
894198092Srdivacky
895193326Sed  /// getArgIdentifier - Return the specified IdentifierInfo argument.
896193326Sed  const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
897193326Sed    assert(getArgKind(Idx) == Diagnostic::ak_identifierinfo &&
898193326Sed           "invalid argument accessor!");
899193326Sed    return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
900193326Sed  }
901198092Srdivacky
902193326Sed  /// getRawArg - Return the specified non-string argument in an opaque form.
903193326Sed  intptr_t getRawArg(unsigned Idx) const {
904193326Sed    assert(getArgKind(Idx) != Diagnostic::ak_std_string &&
905193326Sed           "invalid argument accessor!");
906193326Sed    return DiagObj->DiagArgumentsVal[Idx];
907193326Sed  }
908198092Srdivacky
909198092Srdivacky
910193326Sed  /// getNumRanges - Return the number of source ranges associated with this
911193326Sed  /// diagnostic.
912193326Sed  unsigned getNumRanges() const {
913193326Sed    return DiagObj->NumDiagRanges;
914193326Sed  }
915198092Srdivacky
916210299Sed  const CharSourceRange &getRange(unsigned Idx) const {
917193326Sed    assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
918203955Srdivacky    return DiagObj->DiagRanges[Idx];
919193326Sed  }
920198092Srdivacky
921206084Srdivacky  unsigned getNumFixItHints() const {
922206084Srdivacky    return DiagObj->NumFixItHints;
923193326Sed  }
924193326Sed
925206084Srdivacky  const FixItHint &getFixItHint(unsigned Idx) const {
926206084Srdivacky    return DiagObj->FixItHints[Idx];
927193326Sed  }
928193326Sed
929206084Srdivacky  const FixItHint *getFixItHints() const {
930206084Srdivacky    return DiagObj->NumFixItHints?
931206084Srdivacky             &DiagObj->FixItHints[0] : 0;
932193326Sed  }
933193326Sed
934193326Sed  /// FormatDiagnostic - Format this diagnostic into a string, substituting the
935193326Sed  /// formal arguments into the %0 slots.  The result is appended onto the Str
936193326Sed  /// array.
937193326Sed  void FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const;
938202379Srdivacky
939202379Srdivacky  /// FormatDiagnostic - Format the given format-string into the
940202379Srdivacky  /// output buffer using the arguments stored in this diagnostic.
941202379Srdivacky  void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
942202379Srdivacky                        llvm::SmallVectorImpl<char> &OutStr) const;
943204643Srdivacky};
944203955Srdivacky
945204643Srdivacky/**
946218893Sdim * \brief Represents a diagnostic in a form that can be retained until its
947218893Sdim * corresponding source manager is destroyed.
948204643Srdivacky */
949204643Srdivackyclass StoredDiagnostic {
950218893Sdim  unsigned ID;
951204643Srdivacky  Diagnostic::Level Level;
952204643Srdivacky  FullSourceLoc Loc;
953204643Srdivacky  std::string Message;
954210299Sed  std::vector<CharSourceRange> Ranges;
955206084Srdivacky  std::vector<FixItHint> FixIts;
956204643Srdivacky
957204643Srdivackypublic:
958204643Srdivacky  StoredDiagnostic();
959204643Srdivacky  StoredDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info);
960218893Sdim  StoredDiagnostic(Diagnostic::Level Level, unsigned ID,
961218893Sdim                   llvm::StringRef Message);
962204643Srdivacky  ~StoredDiagnostic();
963204643Srdivacky
964204643Srdivacky  /// \brief Evaluates true when this object stores a diagnostic.
965204643Srdivacky  operator bool() const { return Message.size() > 0; }
966204643Srdivacky
967218893Sdim  unsigned getID() const { return ID; }
968204643Srdivacky  Diagnostic::Level getLevel() const { return Level; }
969204643Srdivacky  const FullSourceLoc &getLocation() const { return Loc; }
970204643Srdivacky  llvm::StringRef getMessage() const { return Message; }
971212904Sdim
972212904Sdim  void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
973212904Sdim
974210299Sed  typedef std::vector<CharSourceRange>::const_iterator range_iterator;
975204643Srdivacky  range_iterator range_begin() const { return Ranges.begin(); }
976204643Srdivacky  range_iterator range_end() const { return Ranges.end(); }
977204643Srdivacky  unsigned range_size() const { return Ranges.size(); }
978204643Srdivacky
979206084Srdivacky  typedef std::vector<FixItHint>::const_iterator fixit_iterator;
980204643Srdivacky  fixit_iterator fixit_begin() const { return FixIts.begin(); }
981204643Srdivacky  fixit_iterator fixit_end() const { return FixIts.end(); }
982204643Srdivacky  unsigned fixit_size() const { return FixIts.size(); }
983193326Sed};
984198092Srdivacky
985193326Sed/// DiagnosticClient - This is an abstract interface implemented by clients of
986193326Sed/// the front-end, which formats and prints fully processed diagnostics.
987193326Sedclass DiagnosticClient {
988218893Sdimprotected:
989218893Sdim  unsigned NumWarnings;       // Number of warnings reported
990218893Sdim  unsigned NumErrors;         // Number of errors reported
991218893Sdim
992193326Sedpublic:
993218893Sdim  DiagnosticClient() : NumWarnings(0), NumErrors(0) { }
994218893Sdim
995218893Sdim  unsigned getNumErrors() const { return NumErrors; }
996218893Sdim  unsigned getNumWarnings() const { return NumWarnings; }
997218893Sdim
998193326Sed  virtual ~DiagnosticClient();
999198092Srdivacky
1000198954Srdivacky  /// BeginSourceFile - Callback to inform the diagnostic client that processing
1001198954Srdivacky  /// of a source file is beginning.
1002198954Srdivacky  ///
1003198954Srdivacky  /// Note that diagnostics may be emitted outside the processing of a source
1004198954Srdivacky  /// file, for example during the parsing of command line options. However,
1005198954Srdivacky  /// diagnostics with source range information are required to only be emitted
1006198954Srdivacky  /// in between BeginSourceFile() and EndSourceFile().
1007198954Srdivacky  ///
1008198954Srdivacky  /// \arg LO - The language options for the source file being processed.
1009198954Srdivacky  /// \arg PP - The preprocessor object being used for the source; this optional
1010198954Srdivacky  /// and may not be present, for example when processing AST source files.
1011199482Srdivacky  virtual void BeginSourceFile(const LangOptions &LangOpts,
1012199482Srdivacky                               const Preprocessor *PP = 0) {}
1013198092Srdivacky
1014198954Srdivacky  /// EndSourceFile - Callback to inform the diagnostic client that processing
1015198954Srdivacky  /// of a source file has ended. The diagnostic client should assume that any
1016198954Srdivacky  /// objects made available via \see BeginSourceFile() are inaccessible.
1017198954Srdivacky  virtual void EndSourceFile() {}
1018198954Srdivacky
1019193326Sed  /// IncludeInDiagnosticCounts - This method (whose default implementation
1020198954Srdivacky  /// returns true) indicates whether the diagnostics handled by this
1021198954Srdivacky  /// DiagnosticClient should be included in the number of diagnostics reported
1022198954Srdivacky  /// by Diagnostic.
1023193326Sed  virtual bool IncludeInDiagnosticCounts() const;
1024193326Sed
1025193326Sed  /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
1026193326Sed  /// capturing it to a log as needed.
1027218893Sdim  ///
1028218893Sdim  /// Default implementation just keeps track of the total number of warnings
1029218893Sdim  /// and errors.
1030193326Sed  virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
1031218893Sdim                                const DiagnosticInfo &Info);
1032193326Sed};
1033193326Sed
1034193326Sed}  // end namespace clang
1035193326Sed
1036193326Sed#endif
1037