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