Diagnostic.h revision 08d6e032a2a0a8656d12b3b7b93942987bb12eb7
1710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov//===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- C++ -*-===//
26091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer//
36091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer//                     The LLVM Compiler Infrastructure
46091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer//
57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source
67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details.
76091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer//
86091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer//===----------------------------------------------------------------------===//
927107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling//
1027107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling//  This file defines the Diagnostic-related interfaces.
1127107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling//
1227107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling//===----------------------------------------------------------------------===//
1327107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling
146091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer#ifndef LLVM_CLANG_DIAGNOSTIC_H
156091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer#define LLVM_CLANG_DIAGNOSTIC_H
16674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak
17674be02d525d4e24bc6943ed9274958c580bcfbcJakub Staszak#include "clang/Basic/DiagnosticIDs.h"
186091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer#include "clang/Basic/SourceLocation.h"
19d509d0b532ec2358b3f341d4a4cd1411cb8b5db2Chris Lattner#include "llvm/ADT/ArrayRef.h"
200319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling#include "llvm/ADT/DenseMap.h"
213467e30edf63b6d8a8d446186674ba9e4b7885a9Bill Wendling#include "llvm/ADT/IntrusiveRefCntPtr.h"
2222bd64173981bf1251c4b3bfc684207340534ba3Bill Wendling#include "llvm/ADT/OwningPtr.h"
2322bd64173981bf1251c4b3bfc684207340534ba3Bill Wendling#include "llvm/Support/type_traits.h"
2458d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner
256091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer#include <vector>
266091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer#include <list>
27d426a642a23a234547cbc7061f5bfec157673249Bill Wendling
28702cc91aa1bd41540e8674921ae7ac89a4ff061fBill Wendlingnamespace clang {
29f6670729aabc1fab85238d2b306a1c1767a807bbBill Wendling  class DiagnosticConsumer;
30a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  class DiagnosticBuilder;
312c79ecbd704c656178ffa43d5a58ebe3ca188b40Bill Wendling  class IdentifierInfo;
32ad9a9e15595bc9d5ba1ed752caf8572957f77a3dDuncan Sands  class DeclContext;
33ad9a9e15595bc9d5ba1ed752caf8572957f77a3dDuncan Sands  class LangOptions;
341d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling  class Preprocessor;
3527107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling  class DiagnosticErrorTrap;
3627107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling  class StoredDiagnostic;
371d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling
381d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling/// \brief Annotates a diagnostic with some code that should be
391d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling/// inserted, removed, or replaced to fix the problem.
40034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling///
416765834754cbb3cb0f15b4b15e98c5e73fa50066Bill Wendling/// This kind of hint should be used when we are certain that the
421d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling/// introduction, removal, or modification of a particular (small!)
431d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling/// amount of code will correct a compilation error. The compiler
44f3d1500ab2c7364d3d0fb73a7e1b8c6339ab48b1Bill Wendling/// should also provide full recovery from such errors, such that
451d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling/// suppressing the diagnostic output can still result in successful
4611d00420e42ba88c3b48cab997965a7be79315e2Bill Wendling/// compilation.
4711d00420e42ba88c3b48cab997965a7be79315e2Bill Wendlingclass FixItHint {
48f3d1500ab2c7364d3d0fb73a7e1b8c6339ab48b1Bill Wendlingpublic:
4911d00420e42ba88c3b48cab997965a7be79315e2Bill Wendling  /// \brief Code that should be replaced to correct the error. Empty for an
5011d00420e42ba88c3b48cab997965a7be79315e2Bill Wendling  /// insertion hint.
5111d00420e42ba88c3b48cab997965a7be79315e2Bill Wendling  CharSourceRange RemoveRange;
52f3d1500ab2c7364d3d0fb73a7e1b8c6339ab48b1Bill Wendling
5311d00420e42ba88c3b48cab997965a7be79315e2Bill Wendling  /// \brief The actual code to insert at the insertion location, as a
5411d00420e42ba88c3b48cab997965a7be79315e2Bill Wendling  /// string.
5511d00420e42ba88c3b48cab997965a7be79315e2Bill Wendling  std::string CodeToInsert;
5611d00420e42ba88c3b48cab997965a7be79315e2Bill Wendling
5711d00420e42ba88c3b48cab997965a7be79315e2Bill Wendling  /// \brief Empty code modification hint, indicating that no code
5811d00420e42ba88c3b48cab997965a7be79315e2Bill Wendling  /// modification is known.
59629fb82419d9bfff6ae475363bcce66192dfcc8eBill Wendling  FixItHint() : RemoveRange() { }
605a0eeb5a9d727940b1dbe8dff6e9aa292ada0f6aBill Wendling
61480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  bool isNull() const {
62480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling    return !RemoveRange.isValid();
63480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  }
646765834754cbb3cb0f15b4b15e98c5e73fa50066Bill Wendling
65f6670729aabc1fab85238d2b306a1c1767a807bbBill Wendling  /// \brief Create a code modification hint that inserts the given
66480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  /// code string at a specific location.
67480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  static FixItHint CreateInsertion(SourceLocation InsertionLoc,
68480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling                                   StringRef Code) {
69480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling    FixItHint Hint;
709a419f656e278b96e9dfe739cd63c7bff9a4e1fdQuentin Colombet    Hint.RemoveRange =
71480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling      CharSourceRange(SourceRange(InsertionLoc, InsertionLoc), false);
72480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling    Hint.CodeToInsert = Code;
73480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling    return Hint;
74480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  }
7567ae13575900e8efd056672987249fd0adbf5e73James Molloy
76480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  /// \brief Create a code modification hint that removes the given
77480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  /// source range.
78480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  static FixItHint CreateRemoval(CharSourceRange RemoveRange) {
793a106e60366a51b4594ec303ff8dbbc58913227fBill Wendling    FixItHint Hint;
80480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling    Hint.RemoveRange = RemoveRange;
81480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling    return Hint;
82480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  }
83480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  static FixItHint CreateRemoval(SourceRange RemoveRange) {
84480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling    return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange));
85480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  }
86480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling
87480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  /// \brief Create a code modification hint that replaces the given
88480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  /// source range with the given code string.
896765834754cbb3cb0f15b4b15e98c5e73fa50066Bill Wendling  static FixItHint CreateReplacement(CharSourceRange RemoveRange,
906765834754cbb3cb0f15b4b15e98c5e73fa50066Bill Wendling                                     StringRef Code) {
91f6670729aabc1fab85238d2b306a1c1767a807bbBill Wendling    FixItHint Hint;
92480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling    Hint.RemoveRange = RemoveRange;
93480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling    Hint.CodeToInsert = Code;
94114baee1fa017daefad2339c77b45b9ca3d79a41Bill Wendling    return Hint;
95480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling  }
96480b1b28ea6fc1bb5c78d99472df624cfd3fce47Bill Wendling
970319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  static FixItHint CreateReplacement(SourceRange RemoveRange,
980319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling                                     StringRef Code) {
993a4779a9211281a1d0c27c97037342329035a185NAKAMURA Takumi    return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code);
1003a4779a9211281a1d0c27c97037342329035a185NAKAMURA Takumi  }
1016f78fbbc630d2b86fb752574f5ad74473f57dfb1Chandler Carruth};
1026f78fbbc630d2b86fb752574f5ad74473f57dfb1Chandler Carruth
1036765834754cbb3cb0f15b4b15e98c5e73fa50066Bill Wendling/// DiagnosticsEngine - This concrete class is used by the front-end to report
1046765834754cbb3cb0f15b4b15e98c5e73fa50066Bill Wendling/// problems and issues.  It massages the diagnostics (e.g. handling things like
10527107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling/// "report warnings as errors" and passes them off to the DiagnosticConsumer
10627107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling/// for reporting to the user. DiagnosticsEngine is tied to one translation unit
107d426a642a23a234547cbc7061f5bfec157673249Bill Wendling/// and one SourceManager.
10827107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendlingclass DiagnosticsEngine : public llvm::RefCountedBase<DiagnosticsEngine> {
1092c79ecbd704c656178ffa43d5a58ebe3ca188b40Bill Wendlingpublic:
110c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling  /// Level - The level of the diagnostic, after it has been through mapping.
11116f95669ec814d98ce28ad514df603c01d662ee8Bill Wendling  enum Level {
112034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling    Ignored = DiagnosticIDs::Ignored,
1132c79ecbd704c656178ffa43d5a58ebe3ca188b40Bill Wendling    Note = DiagnosticIDs::Note,
114c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling    Warning = DiagnosticIDs::Warning,
115c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling    Error = DiagnosticIDs::Error,
116c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling    Fatal = DiagnosticIDs::Fatal
117c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling  };
118c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling
1191d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling  /// ExtensionHandling - How do we handle otherwise-unmapped extension?  This
120629fb82419d9bfff6ae475363bcce66192dfcc8eBill Wendling  /// is controlled by -pedantic and -pedantic-errors.
1212e879bcd52583335c753c005d203bf2ffe8b67b5Bill Wendling  enum ExtensionHandling {
1221d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling    Ext_Ignore, Ext_Warn, Ext_Error
12305cc40d20c0f3b2f1bd5cb86ceb9f32d07cae110Bill Wendling  };
1242e879bcd52583335c753c005d203bf2ffe8b67b5Bill Wendling
1251d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling  enum ArgumentKind {
126ef99fe8efaa6cb74c66e570a6ef467debca92911Bill Wendling    ak_std_string,      // std::string
127e66f3d3ba0ea9f82f65a29c47fc37e997cbf0aceBill Wendling    ak_c_string,        // const char *
128ef99fe8efaa6cb74c66e570a6ef467debca92911Bill Wendling    ak_sint,            // int
1291d3dcfe4246b4d45fa78a8dfd0a11c7fff842c15Bill Wendling    ak_uint,            // unsigned
130943c29135e03e55f9a5dab393786171a4a536482Bill Wendling    ak_identifierinfo,  // IdentifierInfo
131e66f3d3ba0ea9f82f65a29c47fc37e997cbf0aceBill Wendling    ak_qualtype,        // QualType
13230b483c94001927b3593ed200e823104bab51660Bill Wendling    ak_declarationname, // DeclarationName
13360507d53e7e8e6b0c537675f68204a93c3033de7Bill Wendling    ak_nameddecl,       // NamedDecl *
13492e287f5bde8d34af9c3f2979afb6cd05bfb452cBill Wendling    ak_nestednamespec,  // NestedNameSpecifier *
13592e287f5bde8d34af9c3f2979afb6cd05bfb452cBill Wendling    ak_declcontext      // DeclContext *
13692e287f5bde8d34af9c3f2979afb6cd05bfb452cBill Wendling  };
137c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling
1383467e30edf63b6d8a8d446186674ba9e4b7885a9Bill Wendling  /// Specifies which overload candidates to display when overload resolution
1393467e30edf63b6d8a8d446186674ba9e4b7885a9Bill Wendling  /// fails.
140c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling  enum OverloadsShown {
141c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling    Ovl_All,  ///< Show all overloads.
142c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling    Ovl_Best  ///< Show just the "best" overload candidates.
143c08a5ef6581f2c7550e92d31f63cd65ec29c39e0Bill Wendling  };
144bb08593980b16fbd9758da6ca4fa9c7964f2f926Bill Wendling
145bb08593980b16fbd9758da6ca4fa9c7964f2f926Bill Wendling  /// ArgumentValue - This typedef represents on argument value, which is a
146bb08593980b16fbd9758da6ca4fa9c7964f2f926Bill Wendling  /// union discriminated by ArgumentKind, with a value.
1473467e30edf63b6d8a8d446186674ba9e4b7885a9Bill Wendling  typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;
1481db9b6957c2565a2322206bd5907530895f1c7acBill Wendling
149827cde1c8319e51463007078a7ce3660ebc93036Duncan Sandsprivate:
150827cde1c8319e51463007078a7ce3660ebc93036Duncan Sands  unsigned char AllExtensionsSilenced; // Used by __extension__
151e66f3d3ba0ea9f82f65a29c47fc37e997cbf0aceBill Wendling  bool IgnoreAllWarnings;        // Ignore all warnings: -w
15227107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling  bool WarningsAsErrors;         // Treat warnings like errors.
1530319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  bool EnableAllWarnings;        // Enable all warnings.
1540319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  bool ErrorsAsFatal;            // Treat errors like fatal errors.
1550319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  bool SuppressSystemWarnings;   // Suppress warnings in system headers.
1560319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  bool SuppressAllDiagnostics;   // Suppress all diagnostics.
1576f78fbbc630d2b86fb752574f5ad74473f57dfb1Chandler Carruth  OverloadsShown ShowOverloads;  // Which overload candidates to show.
1580319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  unsigned ErrorLimit;           // Cap of # errors emitted, 0 -> no limit.
1590319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack,
1606f78fbbc630d2b86fb752574f5ad74473f57dfb1Chandler Carruth                                   // 0 -> no limit.
1610319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation
1620319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling                                    // backtrace stack, 0 -> no limit.
1630319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors?
1640319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags;
1650319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  DiagnosticConsumer *Client;
1660319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  bool OwnsDiagClient;
1670319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  SourceManager *SourceMgr;
1680319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling
1690319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  /// \brief Mapping information for diagnostics.  Mapping info is
1700319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  /// packed into four bits per diagnostic.  The low three bits are the mapping
1710319888773b36dd61d7d2283cb9a26cac1e5abe8Bill Wendling  /// (an instance of diag::Mapping), or zero if unset.  The high bit is set
17299faa3b4ec6d03ac7808fe4ff3fbf3d04e375502Bill Wendling  /// when the mapping was established as a user mapping.  If the high bit is
17358d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  /// clear, then the low bits are set to the default value, and should be
17458d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  /// mapped with -pedantic, -Werror, etc.
175a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  ///
17618e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  /// A new DiagState is created and kept around when diagnostic pragmas modify
17708c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling  /// the state so that we know what is the diagnostic state at any given
17808c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling  /// source location.
17908c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling  class DiagState {
18008c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling    llvm::DenseMap<unsigned, DiagnosticMappingInfo> DiagMap;
18108c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling
18208c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling  public:
18308c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling    typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::iterator
18408c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling      iterator;
18508c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling    typedef llvm::DenseMap<unsigned, DiagnosticMappingInfo>::const_iterator
18608c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling      const_iterator;
18708c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling
18808c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling    void setMappingInfo(diag::kind Diag, DiagnosticMappingInfo Info) {
18908c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling      DiagMap[Diag] = Info;
19008c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling    }
19108c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling
19208c11d302325b3715d77f4208d183c9b2a253b14Bill Wendling    DiagnosticMappingInfo &getOrAddMappingInfo(diag::kind Diag);
193710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov
19418e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling    const_iterator begin() const { return DiagMap.begin(); }
19527107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling    const_iterator end() const { return DiagMap.end(); }
19627107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling  };
19718e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling
19899faa3b4ec6d03ac7808fe4ff3fbf3d04e375502Bill Wendling  /// \brief Keeps and automatically disposes all DiagStates that we create.
19907aae2e7d58fe23e370e0cbb9e1a3def99434c36Bill Wendling  std::list<DiagState> DiagStates;
20007aae2e7d58fe23e370e0cbb9e1a3def99434c36Bill Wendling
20107aae2e7d58fe23e370e0cbb9e1a3def99434c36Bill Wendling  /// \brief Represents a point in source where the diagnostic state was
20207aae2e7d58fe23e370e0cbb9e1a3def99434c36Bill Wendling  /// modified because of a pragma. 'Loc' can be null if the point represents
20307aae2e7d58fe23e370e0cbb9e1a3def99434c36Bill Wendling  /// the diagnostic state modifications done through the command-line.
20407aae2e7d58fe23e370e0cbb9e1a3def99434c36Bill Wendling  struct DiagStatePoint {
205a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling    DiagState *State;
2067d38c109aab8654e63e9071c7d948661f6b58433Bill Wendling    FullSourceLoc Loc;
207a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling    DiagStatePoint(DiagState *State, FullSourceLoc Loc)
20818e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling      : State(State), Loc(Loc) { }
2090976e00fd1cbf4128daeb72efd8957d00383fda9Bill Wendling
210ec2589863b32da169240c4fa120ef1e3798615d4Bill Wendling    bool operator<(const DiagStatePoint &RHS) const {
2110976e00fd1cbf4128daeb72efd8957d00383fda9Bill Wendling      // If Loc is invalid it means it came from <command-line>, in which case
21218e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling      // we regard it as coming before any valid source location.
2130976e00fd1cbf4128daeb72efd8957d00383fda9Bill Wendling      if (RHS.Loc.isInvalid())
214034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling        return false;
2150976e00fd1cbf4128daeb72efd8957d00383fda9Bill Wendling      if (Loc.isInvalid())
216defaca00b8087d452df2b783250a48a32658a910Bill Wendling        return true;
217defaca00b8087d452df2b783250a48a32658a910Bill Wendling      return Loc.isBeforeInTranslationUnitThan(RHS.Loc);
218defaca00b8087d452df2b783250a48a32658a910Bill Wendling    }
219defaca00b8087d452df2b783250a48a32658a910Bill Wendling  };
220defaca00b8087d452df2b783250a48a32658a910Bill Wendling
2218246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  /// \brief A vector of all DiagStatePoints representing changes in diagnostic
2228246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  /// state due to diagnostic pragmas. The vector is always sorted according to
2238246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  /// the SourceLocation of the DiagStatePoint.
2248246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  typedef std::vector<DiagStatePoint> DiagStatePointsTy;
2258246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  mutable DiagStatePointsTy DiagStatePoints;
2267d38c109aab8654e63e9071c7d948661f6b58433Bill Wendling
2277d38c109aab8654e63e9071c7d948661f6b58433Bill Wendling  /// \brief Keeps the DiagState that was active during each diagnostic 'push'
2287d38c109aab8654e63e9071c7d948661f6b58433Bill Wendling  /// so we can get back at it when we 'pop'.
2297d38c109aab8654e63e9071c7d948661f6b58433Bill Wendling  std::vector<DiagState *> DiagStateOnPushStack;
230ec2589863b32da169240c4fa120ef1e3798615d4Bill Wendling
23158d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  DiagState *GetCurDiagState() const {
232ec2589863b32da169240c4fa120ef1e3798615d4Bill Wendling    assert(!DiagStatePoints.empty());
233ec2589863b32da169240c4fa120ef1e3798615d4Bill Wendling    return DiagStatePoints.back().State;
23499faa3b4ec6d03ac7808fe4ff3fbf3d04e375502Bill Wendling  }
235710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov
23658d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  void PushDiagStatePoint(DiagState *State, SourceLocation L) {
2370598866c052147c31b808391f58434ce3dbfb838Devang Patel    FullSourceLoc Loc(L, *SourceMgr);
23858d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner    // Make sure that DiagStatePoints is always sorted according to Loc.
239710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov    assert((Loc.isValid() || DiagStatePoints.empty()) &&
24018e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling           "Adding invalid loc point after another point");
2418e47daf2858e980210f3e1f007036b24da342c29Bill Wendling    assert((Loc.isInvalid() || DiagStatePoints.empty() ||
24228d65722d6f283b327b5815914382077fe9c0ab4Bill Wendling            DiagStatePoints.back().Loc.isInvalid() ||
24332a57958226e369f964a034da2ce7083a1a34297Bill Wendling            DiagStatePoints.back().Loc.isBeforeInTranslationUnitThan(Loc)) &&
2441bbd644301ed4d8a7efd4ceb15f71c56fa914f28Bill Wendling           "Previous point loc comes after or is the same as new one");
24558d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner    DiagStatePoints.push_back(DiagStatePoint(State,
246defaca00b8087d452df2b783250a48a32658a910Bill Wendling                                             FullSourceLoc(Loc, *SourceMgr)));
247defaca00b8087d452df2b783250a48a32658a910Bill Wendling  }
248defaca00b8087d452df2b783250a48a32658a910Bill Wendling
249defaca00b8087d452df2b783250a48a32658a910Bill Wendling  /// \brief Finds the DiagStatePoint that contains the diagnostic state of
250710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov  /// the given source location.
251e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling  DiagStatePointsTy::iterator GetDiagStatePointForLoc(SourceLocation Loc) const;
252e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling
253e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling  /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or
254e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling  /// fatal error is emitted, and is sticky.
255e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling  bool ErrorOccurred;
2561b0c54f1c5dd61e56cb7cbc435fcb3319cff628fBill Wendling  bool FatalErrorOccurred;
2571b0c54f1c5dd61e56cb7cbc435fcb3319cff628fBill Wendling
258e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling  /// \brief Indicates that an unrecoverable error has occurred.
259e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling  bool UnrecoverableErrorOccurred;
260e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling
2611b0c54f1c5dd61e56cb7cbc435fcb3319cff628fBill Wendling  /// \brief Counts for DiagnosticErrorTrap to check whether an error occurred
262956f13440a4aa0297606a4412f4aa091d931592aBill Wendling  /// during a parsing section, e.g. during parsing a function.
263956f13440a4aa0297606a4412f4aa091d931592aBill Wendling  unsigned TrapNumErrorsOccurred;
264e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling  unsigned TrapNumUnrecoverableErrorsOccurred;
265e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling
266e4e85f17564c28cd571dda30146c3f310521acf0Bill Wendling  /// LastDiagLevel - This is the level of the last diagnostic emitted.  This is
267956f13440a4aa0297606a4412f4aa091d931592aBill Wendling  /// used to emit continuation diagnostics with the same level as the
26818e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  /// diagnostic that they follow.
2698246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  DiagnosticIDs::Level LastDiagLevel;
27018e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling
2718246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  unsigned NumWarnings;       // Number of warnings reported
2728246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  unsigned NumErrors;         // Number of errors reported
2738246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  unsigned NumErrorsSuppressed; // Number of errors suppressed
2748246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling
2758246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  /// ArgToStringFn - A function pointer that converts an opaque diagnostic
2768246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  /// argument to a strings.  This takes the modifiers and argument that was
2778246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  /// present in the diagnostic.
2788246df61f6de716acf1f8c64fac3c19970a2c174Bill Wendling  ///
279710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov  /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous
28058d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  /// arguments formatted for this diagnostic.  Implementations of this function
2810598866c052147c31b808391f58434ce3dbfb838Devang Patel  /// can use this information to avoid redundancy across arguments.
28258d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  ///
28318e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  /// This is a hack to avoid a layering violation between libbasic and libsema.
28418e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  typedef void (*ArgToStringFnTy)(
28528d65722d6f283b327b5815914382077fe9c0ab4Bill Wendling      ArgumentKind Kind, intptr_t Val,
28619c874638d9478a5d5028854817a5ee72293bb2bDevang Patel      const char *Modifier, unsigned ModifierLen,
28718e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling      const char *Argument, unsigned ArgumentLen,
2883fc4b96b503fa202411317684a2ba02e41e43072Bill Wendling      const ArgumentValue *PrevArgs,
28919c874638d9478a5d5028854817a5ee72293bb2bDevang Patel      unsigned NumPrevArgs,
29018e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling      SmallVectorImpl<char> &Output,
291c5f1bc88a2eb7ad9ff924ca90cf88494e5f947b9Bill Wendling      void *Cookie,
292710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov      SmallVectorImpl<intptr_t> &QualTypeVals);
29318e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  void *ArgToStringCookie;
294956f13440a4aa0297606a4412f4aa091d931592aBill Wendling  ArgToStringFnTy ArgToStringFn;
295710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov
296831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling  /// \brief ID of the "delayed" diagnostic, which is a (typically
297831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling  /// fatal) diagnostic that had to be delayed because it was found
298831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling  /// while emitting another diagnostic.
299831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling  unsigned DelayedDiagID;
300831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling
301831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling  /// \brief First string argument for the delayed diagnostic.
3028e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  std::string DelayedDiagArg1;
3038e47daf2858e980210f3e1f007036b24da342c29Bill Wendling
3048e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  /// \brief Second string argument for the delayed diagnostic.
3058e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  std::string DelayedDiagArg2;
306831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling
307831737d329a727f53a1fb0572f7b7a8127208881Bill Wendlingpublic:
308831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling  explicit DiagnosticsEngine(
309831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling                      const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &Diags,
310831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling                      DiagnosticConsumer *client = 0,
311831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling                      bool ShouldOwnClient = true);
3121db9b6957c2565a2322206bd5907530895f1c7acBill Wendling  ~DiagnosticsEngine();
313831737d329a727f53a1fb0572f7b7a8127208881Bill Wendling
31418e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  const llvm::IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const {
31518e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling    return Diags;
316629fb82419d9bfff6ae475363bcce66192dfcc8eBill Wendling  }
31758d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner
318041221c0972ff575b07f76808c504833d629ae1fChris Lattner  DiagnosticConsumer *getClient() { return Client; }
31918e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  const DiagnosticConsumer *getClient() const { return Client; }
320ec2589863b32da169240c4fa120ef1e3798615d4Bill Wendling
32118e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  /// \brief Determine whether this \c DiagnosticsEngine object own its client.
32218e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  bool ownsClient() const { return OwnsDiagClient; }
323ec2589863b32da169240c4fa120ef1e3798615d4Bill Wendling
32418e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  /// \brief Return the current diagnostic client along with ownership of that
325710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov  /// client.
32658d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  DiagnosticConsumer *takeClient() {
3270598866c052147c31b808391f58434ce3dbfb838Devang Patel    OwnsDiagClient = false;
32858d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner    return Client;
329710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov  }
33018e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling
33158d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  bool hasSourceManager() const { return SourceMgr != 0; }
332ec2589863b32da169240c4fa120ef1e3798615d4Bill Wendling  SourceManager &getSourceManager() const {
33358d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner    assert(SourceMgr && "SourceManager not set!");
334710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov    return *SourceMgr;
335034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling  }
336034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling  void setSourceManager(SourceManager *SrcMgr) { SourceMgr = SrcMgr; }
337034b94b17006f51722886b0f2283fb6fb19aca1fBill Wendling
338710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov  //===--------------------------------------------------------------------===//
33918e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  //  DiagnosticsEngine characterization methods, used by a client to customize
34058d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  //  how diagnostics are emitted.
341ec2589863b32da169240c4fa120ef1e3798615d4Bill Wendling  //
34258d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner
343710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov  /// pushMappings - Copies the current DiagMappings and pushes the new copy
34418e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  /// onto the top of the stack.
34518e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling  void pushMappings(SourceLocation Loc);
34618e7211068c9d2c6204512f9c468ee179818a4b6Bill Wendling
34758d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  /// popMappings - Pops the current DiagMappings off the top of the stack
348710632d07b13609444626367bebd34c0af3acb6aMikhail Glushenkov  /// causing the new top of the stack to be the active mappings. Returns
349e1f95db4803a48a30fc2a1d5868281a87a36fb85Bill Wendling  /// true if the pop happens, false if there is only one DiagMapping on the
350e1f95db4803a48a30fc2a1d5868281a87a36fb85Bill Wendling  /// stack.
351e1f95db4803a48a30fc2a1d5868281a87a36fb85Bill Wendling  bool popMappings(SourceLocation Loc);
3528e47daf2858e980210f3e1f007036b24da342c29Bill Wendling
3538e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  /// \brief Set the diagnostic client associated with this diagnostic object.
3548e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  ///
355f3d1500ab2c7364d3d0fb73a7e1b8c6339ab48b1Bill Wendling  /// \param ShouldOwnClient true if the diagnostic object should take
35658d74910c6b82e622ecbb57d6644d48fec5a5c0fChris Lattner  /// ownership of \c client.
3574f859aa532dbf061736f9c23e0d0882b5cdfe566Reid Spencer  void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true);
358a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
359a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// setErrorLimit - Specify a limit for the number of errors we should
360a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// emit before giving up.  Zero disables the limit.
361a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; }
362a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
363a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// \brief Specify the maximum number of template instantiation
364a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// notes to emit along with a given diagnostic.
365a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setTemplateBacktraceLimit(unsigned Limit) {
366a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling    TemplateBacktraceLimit = Limit;
367a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  }
368a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
369a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// \brief Retrieve the maximum number of template instantiation
370a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// notes to emit along with a given diagnostic.
371a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  unsigned getTemplateBacktraceLimit() const {
372a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling    return TemplateBacktraceLimit;
373a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  }
374a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
375a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// \brief Specify the maximum number of constexpr evaluation
376a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// notes to emit along with a given diagnostic.
377a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setConstexprBacktraceLimit(unsigned Limit) {
378a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling    ConstexprBacktraceLimit = Limit;
379a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  }
380a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
381a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// \brief Retrieve the maximum number of constexpr evaluation
382a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// notes to emit along with a given diagnostic.
383a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  unsigned getConstexprBacktraceLimit() const {
384a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling    return ConstexprBacktraceLimit;
385a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  }
386a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
387a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// setIgnoreAllWarnings - When set to true, any unmapped warnings are
388a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// ignored.  If this and WarningsAsErrors are both set, then this one wins.
389a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; }
390a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; }
391a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
392a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// setEnableAllWarnings - When set to true, any unmapped ignored warnings
393a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// are no longer ignored.  If this and IgnoreAllWarnings are both set,
394a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// then that one wins.
395a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setEnableAllWarnings(bool Val) { EnableAllWarnings = Val; }
396a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  bool getEnableAllWarnngs() const { return EnableAllWarnings; }
397a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
398a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// setWarningsAsErrors - When set to true, any warnings reported are issued
399a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// as errors.
400a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; }
401a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  bool getWarningsAsErrors() const { return WarningsAsErrors; }
402a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
403a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// setErrorsAsFatal - When set to true, any error reported is made a
404a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// fatal error.
405a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setErrorsAsFatal(bool Val) { ErrorsAsFatal = Val; }
406a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  bool getErrorsAsFatal() const { return ErrorsAsFatal; }
407a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
408a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// setSuppressSystemWarnings - When set to true mask warnings that
409a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// come from system headers.
410a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; }
411a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; }
412a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
413a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// \brief Suppress all diagnostics, to silence the front end when we
414a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// know that we don't want any more diagnostics to be passed along to the
415a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// client
416a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setSuppressAllDiagnostics(bool Val = true) {
417a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling    SuppressAllDiagnostics = Val;
418a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  }
419a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; }
420a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
421a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// \brief Specify which overload candidates to show when overload resolution
422a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// fails.  By default, we show all candidates.
423a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setShowOverloads(OverloadsShown Val) {
424a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling    ShowOverloads = Val;
425a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  }
426a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  OverloadsShown getShowOverloads() const { return ShowOverloads; }
427a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
428a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// \brief Pretend that the last diagnostic issued was ignored. This can
429a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// be used by clients who suppress diagnostics themselves.
430a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setLastDiagnosticIgnored() {
431a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling    LastDiagLevel = DiagnosticIDs::Ignored;
432a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  }
433a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
434a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped
435a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// extension diagnostics are mapped onto ignore/warning/error.  This
436a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// corresponds to the GCC -pedantic and -pedantic-errors option.
437a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setExtensionHandlingBehavior(ExtensionHandling H) {
438a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling    ExtBehavior = H;
439a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  }
440a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  ExtensionHandling getExtensionHandlingBehavior() const { return ExtBehavior; }
441a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
442a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// AllExtensionsSilenced - This is a counter bumped when an __extension__
443a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// block is encountered.  When non-zero, all extension diagnostics are
444114baee1fa017daefad2339c77b45b9ca3d79a41Bill Wendling  /// entirely silenced, no matter how they are mapped.
445a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; }
446a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; }
447a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; }
448a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
449a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// \brief This allows the client to specify that certain
450a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// warnings are ignored.  Notes can never be mapped, errors can only be
451a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily.
452a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  ///
453a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// \param Loc The source location that this change of diagnostic state should
454a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// take affect. It can be null if we are setting the latest state.
455a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map,
456a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling                            SourceLocation Loc);
457a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling
4581db9b6957c2565a2322206bd5907530895f1c7acBill Wendling  /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g.
459a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// "unknown-pragmas" to have the specified mapping.  This returns true and
460a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// ignores the request if "Group" was unknown, false otherwise.
461a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  ///
462a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// 'Loc' is the source location that this change of diagnostic state should
463a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  /// take affect. It can be null if we are setting the state from command-line.
464a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling  bool setDiagnosticGroupMapping(StringRef Group, diag::Mapping Map,
465a90a99a82b9c5c39fc6dbee9c266dcd7b107fe2fBill Wendling                                 SourceLocation Loc = SourceLocation());
4668e47daf2858e980210f3e1f007036b24da342c29Bill Wendling
4678e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  /// \brief Set the warning-as-error flag for the given diagnostic group. This
4688e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  /// function always only operates on the current diagnostic state.
4698e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  ///
4708e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  /// \returns True if the given group is unknown, false otherwise.
4718e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled);
4728e47daf2858e980210f3e1f007036b24da342c29Bill Wendling
4738e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  /// \brief Set the error-as-fatal flag for the given diagnostic group. This
4748e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  /// function always only operates on the current diagnostic state.
4758e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  ///
4768e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  /// \returns True if the given group is unknown, false otherwise.
4778e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled);
4788e47daf2858e980210f3e1f007036b24da342c29Bill Wendling
4798e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  bool hasErrorOccurred() const { return ErrorOccurred; }
4808e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  bool hasFatalErrorOccurred() const { return FatalErrorOccurred; }
4818e47daf2858e980210f3e1f007036b24da342c29Bill Wendling
4828e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  /// \brief Determine whether any kind of unrecoverable error has occurred.
4838e47daf2858e980210f3e1f007036b24da342c29Bill Wendling  bool hasUnrecoverableErrorOccurred() const {
48427107f6ab4627fa38bcacad6757ed6d52910f880Bill Wendling    return FatalErrorOccurred || UnrecoverableErrorOccurred;
4856091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer  }
4866091ebd172a16a10f1ea66061a5fa7cbf5139e56Reid Spencer
487  unsigned getNumWarnings() const { return NumWarnings; }
488
489  void setNumWarnings(unsigned NumWarnings) {
490    this->NumWarnings = NumWarnings;
491  }
492
493  /// getCustomDiagID - Return an ID for a diagnostic with the specified message
494  /// and level.  If this is the first request for this diagnosic, it is
495  /// registered and created, otherwise the existing ID is returned.
496  unsigned getCustomDiagID(Level L, StringRef Message) {
497    return Diags->getCustomDiagID((DiagnosticIDs::Level)L, Message);
498  }
499
500  /// ConvertArgToString - This method converts a diagnostic argument (as an
501  /// intptr_t) into the string that represents it.
502  void ConvertArgToString(ArgumentKind Kind, intptr_t Val,
503                          const char *Modifier, unsigned ModLen,
504                          const char *Argument, unsigned ArgLen,
505                          const ArgumentValue *PrevArgs, unsigned NumPrevArgs,
506                          SmallVectorImpl<char> &Output,
507                          SmallVectorImpl<intptr_t> &QualTypeVals) const {
508    ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen,
509                  PrevArgs, NumPrevArgs, Output, ArgToStringCookie,
510                  QualTypeVals);
511  }
512
513  void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) {
514    ArgToStringFn = Fn;
515    ArgToStringCookie = Cookie;
516  }
517
518  /// \brief Reset the state of the diagnostic object to its initial
519  /// configuration.
520  void Reset();
521
522  //===--------------------------------------------------------------------===//
523  // DiagnosticsEngine classification and reporting interfaces.
524  //
525
526  /// \brief Based on the way the client configured the DiagnosticsEngine
527  /// object, classify the specified diagnostic ID into a Level, consumable by
528  /// the DiagnosticConsumer.
529  ///
530  /// \param Loc The source location we are interested in finding out the
531  /// diagnostic state. Can be null in order to query the latest state.
532  Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const {
533    return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this);
534  }
535
536  /// Report - Issue the message to the client.  @c DiagID is a member of the
537  /// @c diag::kind enum.  This actually returns aninstance of DiagnosticBuilder
538  /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed.
539  /// @c Pos represents the source location associated with the diagnostic,
540  /// which can be an invalid location if no position information is available.
541  inline DiagnosticBuilder Report(SourceLocation Pos, unsigned DiagID);
542  inline DiagnosticBuilder Report(unsigned DiagID);
543
544  void Report(const StoredDiagnostic &storedDiag);
545
546  /// \brief Determine whethere there is already a diagnostic in flight.
547  bool isDiagnosticInFlight() const { return CurDiagID != ~0U; }
548
549  /// \brief Set the "delayed" diagnostic that will be emitted once
550  /// the current diagnostic completes.
551  ///
552  ///  If a diagnostic is already in-flight but the front end must
553  ///  report a problem (e.g., with an inconsistent file system
554  ///  state), this routine sets a "delayed" diagnostic that will be
555  ///  emitted after the current diagnostic completes. This should
556  ///  only be used for fatal errors detected at inconvenient
557  ///  times. If emitting a delayed diagnostic causes a second delayed
558  ///  diagnostic to be introduced, that second delayed diagnostic
559  ///  will be ignored.
560  ///
561  /// \param DiagID The ID of the diagnostic being delayed.
562  ///
563  /// \param Arg1 A string argument that will be provided to the
564  /// diagnostic. A copy of this string will be stored in the
565  /// DiagnosticsEngine object itself.
566  ///
567  /// \param Arg2 A string argument that will be provided to the
568  /// diagnostic. A copy of this string will be stored in the
569  /// DiagnosticsEngine object itself.
570  void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "",
571                            StringRef Arg2 = "");
572
573  /// \brief Clear out the current diagnostic.
574  void Clear() { CurDiagID = ~0U; }
575
576private:
577  /// \brief Report the delayed diagnostic.
578  void ReportDelayed();
579
580  // This is private state used by DiagnosticBuilder.  We put it here instead of
581  // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight
582  // object.  This implementation choice means that we can only have one
583  // diagnostic "in flight" at a time, but this seems to be a reasonable
584  // tradeoff to keep these objects small.  Assertions verify that only one
585  // diagnostic is in flight at a time.
586  friend class DiagnosticIDs;
587  friend class DiagnosticBuilder;
588  friend class Diagnostic;
589  friend class PartialDiagnostic;
590  friend class DiagnosticErrorTrap;
591
592  /// CurDiagLoc - This is the location of the current diagnostic that is in
593  /// flight.
594  SourceLocation CurDiagLoc;
595
596  /// CurDiagID - This is the ID of the current diagnostic that is in flight.
597  /// This is set to ~0U when there is no diagnostic in flight.
598  unsigned CurDiagID;
599
600  enum {
601    /// MaxArguments - The maximum number of arguments we can hold. We currently
602    /// only support up to 10 arguments (%0-%9).  A single diagnostic with more
603    /// than that almost certainly has to be simplified anyway.
604    MaxArguments = 10
605  };
606
607  /// NumDiagArgs - This contains the number of entries in Arguments.
608  signed char NumDiagArgs;
609  /// NumRanges - This is the number of ranges in the DiagRanges array.
610  unsigned char NumDiagRanges;
611  /// \brief The number of code modifications hints in the
612  /// FixItHints array.
613  unsigned char NumFixItHints;
614
615  /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
616  /// values, with one for each argument.  This specifies whether the argument
617  /// is in DiagArgumentsStr or in DiagArguments.
618  unsigned char DiagArgumentsKind[MaxArguments];
619
620  /// DiagArgumentsStr - This holds the values of each string argument for the
621  /// current diagnostic.  This value is only used when the corresponding
622  /// ArgumentKind is ak_std_string.
623  std::string DiagArgumentsStr[MaxArguments];
624
625  /// DiagArgumentsVal - The values for the various substitution positions. This
626  /// is used when the argument is not an std::string.  The specific value is
627  /// mangled into an intptr_t and the interpretation depends on exactly what
628  /// sort of argument kind it is.
629  intptr_t DiagArgumentsVal[MaxArguments];
630
631  /// DiagRanges - The list of ranges added to this diagnostic.  It currently
632  /// only support 10 ranges, could easily be extended if needed.
633  CharSourceRange DiagRanges[10];
634
635  enum { MaxFixItHints = 6 };
636
637  /// FixItHints - If valid, provides a hint with some code
638  /// to insert, remove, or modify at a particular position.
639  FixItHint FixItHints[MaxFixItHints];
640
641  DiagnosticMappingInfo makeMappingInfo(diag::Mapping Map, SourceLocation L) {
642    bool isPragma = L.isValid();
643    DiagnosticMappingInfo MappingInfo = DiagnosticMappingInfo::Make(
644      Map, /*IsUser=*/true, isPragma);
645
646    // If this is a pragma mapping, then set the diagnostic mapping flags so
647    // that we override command line options.
648    if (isPragma) {
649      MappingInfo.setNoWarningAsError(true);
650      MappingInfo.setNoErrorAsFatal(true);
651    }
652
653    return MappingInfo;
654  }
655
656  /// ProcessDiag - This is the method used to report a diagnostic that is
657  /// finally fully formed.
658  ///
659  /// \returns true if the diagnostic was emitted, false if it was
660  /// suppressed.
661  bool ProcessDiag() {
662    return Diags->ProcessDiag(*this);
663  }
664
665  friend class ASTReader;
666  friend class ASTWriter;
667};
668
669/// \brief RAII class that determines when any errors have occurred
670/// between the time the instance was created and the time it was
671/// queried.
672class DiagnosticErrorTrap {
673  DiagnosticsEngine &Diag;
674  unsigned NumErrors;
675  unsigned NumUnrecoverableErrors;
676
677public:
678  explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag)
679    : Diag(Diag) { reset(); }
680
681  /// \brief Determine whether any errors have occurred since this
682  /// object instance was created.
683  bool hasErrorOccurred() const {
684    return Diag.TrapNumErrorsOccurred > NumErrors;
685  }
686
687  /// \brief Determine whether any unrecoverable errors have occurred since this
688  /// object instance was created.
689  bool hasUnrecoverableErrorOccurred() const {
690    return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors;
691  }
692
693  // Set to initial state of "no errors occurred".
694  void reset() {
695    NumErrors = Diag.TrapNumErrorsOccurred;
696    NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred;
697  }
698};
699
700//===----------------------------------------------------------------------===//
701// DiagnosticBuilder
702//===----------------------------------------------------------------------===//
703
704/// DiagnosticBuilder - This is a little helper class used to produce
705/// diagnostics.  This is constructed by the DiagnosticsEngine::Report method,
706/// and allows insertion of extra information (arguments and source ranges) into
707/// the currently "in flight" diagnostic.  When the temporary for the builder is
708/// destroyed, the diagnostic is issued.
709///
710/// Note that many of these will be created as temporary objects (many call
711/// sites), so we want them to be small and we never want their address taken.
712/// This ensures that compilers with somewhat reasonable optimizers will promote
713/// the common fields to registers, eliminating increments of the NumArgs field,
714/// for example.
715class DiagnosticBuilder {
716  mutable DiagnosticsEngine *DiagObj;
717  mutable unsigned NumArgs, NumRanges, NumFixItHints;
718
719  void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
720  friend class DiagnosticsEngine;
721  explicit DiagnosticBuilder(DiagnosticsEngine *diagObj)
722    : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {}
723
724  friend class PartialDiagnostic;
725
726protected:
727  void FlushCounts();
728
729public:
730  /// Copy constructor.  When copied, this "takes" the diagnostic info from the
731  /// input and neuters it.
732  DiagnosticBuilder(const DiagnosticBuilder &D) {
733    DiagObj = D.DiagObj;
734    D.DiagObj = 0;
735    NumArgs = D.NumArgs;
736    NumRanges = D.NumRanges;
737    NumFixItHints = D.NumFixItHints;
738  }
739
740  /// \brief Simple enumeration value used to give a name to the
741  /// suppress-diagnostic constructor.
742  enum SuppressKind { Suppress };
743
744  /// \brief Create an empty DiagnosticBuilder object that represents
745  /// no actual diagnostic.
746  explicit DiagnosticBuilder(SuppressKind)
747    : DiagObj(0), NumArgs(0), NumRanges(0), NumFixItHints(0) { }
748
749  /// \brief Force the diagnostic builder to emit the diagnostic now.
750  ///
751  /// Once this function has been called, the DiagnosticBuilder object
752  /// should not be used again before it is destroyed.
753  ///
754  /// \returns true if a diagnostic was emitted, false if the
755  /// diagnostic was suppressed.
756  bool Emit();
757
758  /// Destructor - The dtor emits the diagnostic if it hasn't already
759  /// been emitted.
760  ~DiagnosticBuilder() { Emit(); }
761
762  /// isActive - Determine whether this diagnostic is still active.
763  bool isActive() const { return DiagObj != 0; }
764
765  /// \brief Retrieve the active diagnostic ID.
766  ///
767  /// \pre \c isActive()
768  unsigned getDiagID() const {
769    assert(isActive() && "DiagnosticsEngine is inactive");
770    return DiagObj->CurDiagID;
771  }
772
773  /// \brief Retrieve the active diagnostic's location.
774  ///
775  /// \pre \c isActive()
776  SourceLocation getLocation() const { return DiagObj->CurDiagLoc; }
777
778  /// \brief Clear out the current diagnostic.
779  void Clear() { DiagObj = 0; }
780
781  /// Operator bool: conversion of DiagnosticBuilder to bool always returns
782  /// true.  This allows is to be used in boolean error contexts like:
783  /// return Diag(...);
784  operator bool() const { return true; }
785
786  void AddString(StringRef S) const {
787    assert(NumArgs < DiagnosticsEngine::MaxArguments &&
788           "Too many arguments to diagnostic!");
789    if (DiagObj) {
790      DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string;
791      DiagObj->DiagArgumentsStr[NumArgs++] = S;
792    }
793  }
794
795  void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const {
796    assert(NumArgs < DiagnosticsEngine::MaxArguments &&
797           "Too many arguments to diagnostic!");
798    if (DiagObj) {
799      DiagObj->DiagArgumentsKind[NumArgs] = Kind;
800      DiagObj->DiagArgumentsVal[NumArgs++] = V;
801    }
802  }
803
804  void AddSourceRange(const CharSourceRange &R) const {
805    assert(NumRanges <
806           sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
807           "Too many arguments to diagnostic!");
808    if (DiagObj)
809      DiagObj->DiagRanges[NumRanges++] = R;
810  }
811
812  void AddFixItHint(const FixItHint &Hint) const {
813    assert(NumFixItHints < DiagnosticsEngine::MaxFixItHints &&
814           "Too many fix-it hints!");
815    if (NumFixItHints >= DiagnosticsEngine::MaxFixItHints)
816      return;  // Don't crash in release builds
817    if (DiagObj)
818      DiagObj->FixItHints[NumFixItHints++] = Hint;
819  }
820};
821
822inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
823                                           StringRef S) {
824  DB.AddString(S);
825  return DB;
826}
827
828inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
829                                           const char *Str) {
830  DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str),
831                  DiagnosticsEngine::ak_c_string);
832  return DB;
833}
834
835inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) {
836  DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
837  return DB;
838}
839
840inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) {
841  DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint);
842  return DB;
843}
844
845inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
846                                           unsigned I) {
847  DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint);
848  return DB;
849}
850
851inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
852                                           const IdentifierInfo *II) {
853  DB.AddTaggedVal(reinterpret_cast<intptr_t>(II),
854                  DiagnosticsEngine::ak_identifierinfo);
855  return DB;
856}
857
858// Adds a DeclContext to the diagnostic. The enable_if template magic is here
859// so that we only match those arguments that are (statically) DeclContexts;
860// other arguments that derive from DeclContext (e.g., RecordDecls) will not
861// match.
862template<typename T>
863inline
864typename llvm::enable_if<llvm::is_same<T, DeclContext>,
865                         const DiagnosticBuilder &>::type
866operator<<(const DiagnosticBuilder &DB, T *DC) {
867  DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC),
868                  DiagnosticsEngine::ak_declcontext);
869  return DB;
870}
871
872inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
873                                           const SourceRange &R) {
874  DB.AddSourceRange(CharSourceRange::getTokenRange(R));
875  return DB;
876}
877
878inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
879                                           const CharSourceRange &R) {
880  DB.AddSourceRange(R);
881  return DB;
882}
883
884inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
885                                           const FixItHint &Hint) {
886  DB.AddFixItHint(Hint);
887  return DB;
888}
889
890/// Report - Issue the message to the client.  DiagID is a member of the
891/// diag::kind enum.  This actually returns a new instance of DiagnosticBuilder
892/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
893inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc,
894                                            unsigned DiagID){
895  assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!");
896  CurDiagLoc = Loc;
897  CurDiagID = DiagID;
898  return DiagnosticBuilder(this);
899}
900inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) {
901  return Report(SourceLocation(), DiagID);
902}
903
904//===----------------------------------------------------------------------===//
905// Diagnostic
906//===----------------------------------------------------------------------===//
907
908/// Diagnostic - This is a little helper class (which is basically a smart
909/// pointer that forward info from DiagnosticsEngine) that allows clients to
910/// enquire about the currently in-flight diagnostic.
911class Diagnostic {
912  const DiagnosticsEngine *DiagObj;
913  StringRef StoredDiagMessage;
914public:
915  explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {}
916  Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage)
917    : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {}
918
919  const DiagnosticsEngine *getDiags() const { return DiagObj; }
920  unsigned getID() const { return DiagObj->CurDiagID; }
921  const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; }
922  bool hasSourceManager() const { return DiagObj->hasSourceManager(); }
923  SourceManager &getSourceManager() const { return DiagObj->getSourceManager();}
924
925  unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
926
927  /// getArgKind - Return the kind of the specified index.  Based on the kind
928  /// of argument, the accessors below can be used to get the value.
929  DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const {
930    assert(Idx < getNumArgs() && "Argument index out of range!");
931    return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx];
932  }
933
934  /// getArgStdStr - Return the provided argument string specified by Idx.
935  const std::string &getArgStdStr(unsigned Idx) const {
936    assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string &&
937           "invalid argument accessor!");
938    return DiagObj->DiagArgumentsStr[Idx];
939  }
940
941  /// getArgCStr - Return the specified C string argument.
942  const char *getArgCStr(unsigned Idx) const {
943    assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string &&
944           "invalid argument accessor!");
945    return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]);
946  }
947
948  /// getArgSInt - Return the specified signed integer argument.
949  int getArgSInt(unsigned Idx) const {
950    assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint &&
951           "invalid argument accessor!");
952    return (int)DiagObj->DiagArgumentsVal[Idx];
953  }
954
955  /// getArgUInt - Return the specified unsigned integer argument.
956  unsigned getArgUInt(unsigned Idx) const {
957    assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint &&
958           "invalid argument accessor!");
959    return (unsigned)DiagObj->DiagArgumentsVal[Idx];
960  }
961
962  /// getArgIdentifier - Return the specified IdentifierInfo argument.
963  const IdentifierInfo *getArgIdentifier(unsigned Idx) const {
964    assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo &&
965           "invalid argument accessor!");
966    return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
967  }
968
969  /// getRawArg - Return the specified non-string argument in an opaque form.
970  intptr_t getRawArg(unsigned Idx) const {
971    assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string &&
972           "invalid argument accessor!");
973    return DiagObj->DiagArgumentsVal[Idx];
974  }
975
976
977  /// getNumRanges - Return the number of source ranges associated with this
978  /// diagnostic.
979  unsigned getNumRanges() const {
980    return DiagObj->NumDiagRanges;
981  }
982
983  const CharSourceRange &getRange(unsigned Idx) const {
984    assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
985    return DiagObj->DiagRanges[Idx];
986  }
987
988  /// \brief Return an array reference for this diagnostic's ranges.
989  ArrayRef<CharSourceRange> getRanges() const {
990    return llvm::makeArrayRef(DiagObj->DiagRanges, DiagObj->NumDiagRanges);
991  }
992
993  unsigned getNumFixItHints() const {
994    return DiagObj->NumFixItHints;
995  }
996
997  const FixItHint &getFixItHint(unsigned Idx) const {
998    return DiagObj->FixItHints[Idx];
999  }
1000
1001  const FixItHint *getFixItHints() const {
1002    return DiagObj->NumFixItHints?
1003             &DiagObj->FixItHints[0] : 0;
1004  }
1005
1006  /// FormatDiagnostic - Format this diagnostic into a string, substituting the
1007  /// formal arguments into the %0 slots.  The result is appended onto the Str
1008  /// array.
1009  void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const;
1010
1011  /// FormatDiagnostic - Format the given format-string into the
1012  /// output buffer using the arguments stored in this diagnostic.
1013  void FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
1014                        SmallVectorImpl<char> &OutStr) const;
1015};
1016
1017/**
1018 * \brief Represents a diagnostic in a form that can be retained until its
1019 * corresponding source manager is destroyed.
1020 */
1021class StoredDiagnostic {
1022  unsigned ID;
1023  DiagnosticsEngine::Level Level;
1024  FullSourceLoc Loc;
1025  std::string Message;
1026  std::vector<CharSourceRange> Ranges;
1027  std::vector<FixItHint> FixIts;
1028
1029public:
1030  StoredDiagnostic();
1031  StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info);
1032  StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1033                   StringRef Message);
1034  StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID,
1035                   StringRef Message, FullSourceLoc Loc,
1036                   ArrayRef<CharSourceRange> Ranges,
1037                   ArrayRef<FixItHint> Fixits);
1038  ~StoredDiagnostic();
1039
1040  /// \brief Evaluates true when this object stores a diagnostic.
1041  operator bool() const { return Message.size() > 0; }
1042
1043  unsigned getID() const { return ID; }
1044  DiagnosticsEngine::Level getLevel() const { return Level; }
1045  const FullSourceLoc &getLocation() const { return Loc; }
1046  StringRef getMessage() const { return Message; }
1047
1048  void setLocation(FullSourceLoc Loc) { this->Loc = Loc; }
1049
1050  typedef std::vector<CharSourceRange>::const_iterator range_iterator;
1051  range_iterator range_begin() const { return Ranges.begin(); }
1052  range_iterator range_end() const { return Ranges.end(); }
1053  unsigned range_size() const { return Ranges.size(); }
1054
1055  typedef std::vector<FixItHint>::const_iterator fixit_iterator;
1056  fixit_iterator fixit_begin() const { return FixIts.begin(); }
1057  fixit_iterator fixit_end() const { return FixIts.end(); }
1058  unsigned fixit_size() const { return FixIts.size(); }
1059};
1060
1061/// DiagnosticConsumer - This is an abstract interface implemented by clients of
1062/// the front-end, which formats and prints fully processed diagnostics.
1063class DiagnosticConsumer {
1064protected:
1065  unsigned NumWarnings;       // Number of warnings reported
1066  unsigned NumErrors;         // Number of errors reported
1067
1068public:
1069  DiagnosticConsumer() : NumWarnings(0), NumErrors(0) { }
1070
1071  unsigned getNumErrors() const { return NumErrors; }
1072  unsigned getNumWarnings() const { return NumWarnings; }
1073
1074  virtual ~DiagnosticConsumer();
1075
1076  /// BeginSourceFile - Callback to inform the diagnostic client that processing
1077  /// of a source file is beginning.
1078  ///
1079  /// Note that diagnostics may be emitted outside the processing of a source
1080  /// file, for example during the parsing of command line options. However,
1081  /// diagnostics with source range information are required to only be emitted
1082  /// in between BeginSourceFile() and EndSourceFile().
1083  ///
1084  /// \arg LO - The language options for the source file being processed.
1085  /// \arg PP - The preprocessor object being used for the source; this optional
1086  /// and may not be present, for example when processing AST source files.
1087  virtual void BeginSourceFile(const LangOptions &LangOpts,
1088                               const Preprocessor *PP = 0) {}
1089
1090  /// EndSourceFile - Callback to inform the diagnostic client that processing
1091  /// of a source file has ended. The diagnostic client should assume that any
1092  /// objects made available via \see BeginSourceFile() are inaccessible.
1093  virtual void EndSourceFile() {}
1094
1095  /// \brief Callback to inform the diagnostic client that processing of all
1096  /// source files has ended.
1097  virtual void finish() {}
1098
1099  /// IncludeInDiagnosticCounts - This method (whose default implementation
1100  /// returns true) indicates whether the diagnostics handled by this
1101  /// DiagnosticConsumer should be included in the number of diagnostics
1102  /// reported by DiagnosticsEngine.
1103  virtual bool IncludeInDiagnosticCounts() const;
1104
1105  /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
1106  /// capturing it to a log as needed.
1107  ///
1108  /// Default implementation just keeps track of the total number of warnings
1109  /// and errors.
1110  virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1111                                const Diagnostic &Info);
1112
1113  /// \brief Clone the diagnostic consumer, producing an equivalent consumer
1114  /// that can be used in a different context.
1115  virtual DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const = 0;
1116};
1117
1118/// IgnoringDiagConsumer - This is a diagnostic client that just ignores all
1119/// diags.
1120class IgnoringDiagConsumer : public DiagnosticConsumer {
1121  void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
1122                        const Diagnostic &Info) {
1123    // Just ignore it.
1124  }
1125  DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
1126    return new IgnoringDiagConsumer();
1127  }
1128};
1129
1130}  // end namespace clang
1131
1132#endif
1133