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