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