1341825Sdim//===- Diagnostic.h - C Language Family Diagnostic Handling -----*- C++ -*-===// 2193326Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193326Sed// 7193326Sed//===----------------------------------------------------------------------===// 8341825Sdim// 9239462Sdim/// \file 10341825Sdim/// Defines the Diagnostic-related interfaces. 11341825Sdim// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14280031Sdim#ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_H 15280031Sdim#define LLVM_CLANG_BASIC_DIAGNOSTIC_H 16193326Sed 17218893Sdim#include "clang/Basic/DiagnosticIDs.h" 18243830Sdim#include "clang/Basic/DiagnosticOptions.h" 19193326Sed#include "clang/Basic/SourceLocation.h" 20288943Sdim#include "clang/Basic/Specifiers.h" 21226633Sdim#include "llvm/ADT/ArrayRef.h" 22218893Sdim#include "llvm/ADT/DenseMap.h" 23206275Srdivacky#include "llvm/ADT/IntrusiveRefCntPtr.h" 24314564Sdim#include "llvm/ADT/SmallVector.h" 25314564Sdim#include "llvm/ADT/StringRef.h" 26341825Sdim#include "llvm/ADT/iterator_range.h" 27341825Sdim#include "llvm/Support/Compiler.h" 28353358Sdim#include "llvm/Support/Error.h" 29314564Sdim#include <cassert> 30314564Sdim#include <cstdint> 31341825Sdim#include <limits> 32249423Sdim#include <list> 33321369Sdim#include <map> 34314564Sdim#include <memory> 35314564Sdim#include <string> 36314564Sdim#include <type_traits> 37314564Sdim#include <utility> 38198092Srdivacky#include <vector> 39193326Sed 40193326Sednamespace clang { 41314564Sdim 42314564Sdimclass DeclContext; 43314564Sdimclass DiagnosticBuilder; 44314564Sdimclass DiagnosticConsumer; 45314564Sdimclass IdentifierInfo; 46314564Sdimclass LangOptions; 47314564Sdimclass Preprocessor; 48341825Sdimclass SourceManager; 49314564Sdimclass StoredDiagnostic; 50314564Sdim 51314564Sdimnamespace tok { 52314564Sdim 53341825Sdimenum TokenKind : unsigned short; 54198092Srdivacky 55341825Sdim} // namespace tok 56314564Sdim 57341825Sdim/// Annotates a diagnostic with some code that should be 58193326Sed/// inserted, removed, or replaced to fix the problem. 59193326Sed/// 60193326Sed/// This kind of hint should be used when we are certain that the 61193326Sed/// introduction, removal, or modification of a particular (small!) 62193326Sed/// amount of code will correct a compilation error. The compiler 63193326Sed/// should also provide full recovery from such errors, such that 64193326Sed/// suppressing the diagnostic output can still result in successful 65193326Sed/// compilation. 66206084Srdivackyclass FixItHint { 67193326Sedpublic: 68341825Sdim /// Code that should be replaced to correct the error. Empty for an 69212904Sdim /// insertion hint. 70210299Sed CharSourceRange RemoveRange; 71193326Sed 72341825Sdim /// Code in the specific range that should be inserted in the insertion 73234353Sdim /// location. 74234353Sdim CharSourceRange InsertFromRange; 75234353Sdim 76341825Sdim /// The actual code to insert at the insertion location, as a 77193326Sed /// string. 78193326Sed std::string CodeToInsert; 79193326Sed 80341825Sdim bool BeforePreviousInsertions = false; 81234353Sdim 82341825Sdim /// Empty code modification hint, indicating that no code 83193326Sed /// modification is known. 84341825Sdim FixItHint() = default; 85193326Sed 86199482Srdivacky bool isNull() const { 87212904Sdim return !RemoveRange.isValid(); 88199482Srdivacky } 89341825Sdim 90341825Sdim /// Create a code modification hint that inserts the given 91193326Sed /// code string at a specific location. 92206084Srdivacky static FixItHint CreateInsertion(SourceLocation InsertionLoc, 93234353Sdim StringRef Code, 94234353Sdim bool BeforePreviousInsertions = false) { 95206084Srdivacky FixItHint Hint; 96212904Sdim Hint.RemoveRange = 97249423Sdim CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); 98193326Sed Hint.CodeToInsert = Code; 99234353Sdim Hint.BeforePreviousInsertions = BeforePreviousInsertions; 100193326Sed return Hint; 101193326Sed } 102341825Sdim 103341825Sdim /// Create a code modification hint that inserts the given 104239462Sdim /// code from \p FromRange at a specific location. 105234353Sdim static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc, 106234353Sdim CharSourceRange FromRange, 107234353Sdim bool BeforePreviousInsertions = false) { 108234353Sdim FixItHint Hint; 109234353Sdim Hint.RemoveRange = 110249423Sdim CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); 111234353Sdim Hint.InsertFromRange = FromRange; 112234353Sdim Hint.BeforePreviousInsertions = BeforePreviousInsertions; 113234353Sdim return Hint; 114234353Sdim } 115193326Sed 116341825Sdim /// Create a code modification hint that removes the given 117193326Sed /// source range. 118210299Sed static FixItHint CreateRemoval(CharSourceRange RemoveRange) { 119206084Srdivacky FixItHint Hint; 120193326Sed Hint.RemoveRange = RemoveRange; 121193326Sed return Hint; 122193326Sed } 123210299Sed static FixItHint CreateRemoval(SourceRange RemoveRange) { 124210299Sed return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange)); 125210299Sed } 126341825Sdim 127341825Sdim /// Create a code modification hint that replaces the given 128193326Sed /// source range with the given code string. 129210299Sed static FixItHint CreateReplacement(CharSourceRange RemoveRange, 130226633Sdim StringRef Code) { 131206084Srdivacky FixItHint Hint; 132193326Sed Hint.RemoveRange = RemoveRange; 133193326Sed Hint.CodeToInsert = Code; 134193326Sed return Hint; 135193326Sed } 136341825Sdim 137210299Sed static FixItHint CreateReplacement(SourceRange RemoveRange, 138226633Sdim StringRef Code) { 139210299Sed return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code); 140210299Sed } 141193326Sed}; 142193326Sed 143341825Sdim/// Concrete class used by the front-end to report problems and issues. 144239462Sdim/// 145239462Sdim/// This massages the diagnostics (e.g. handling things like "report warnings 146239462Sdim/// as errors" and passes them off to the DiagnosticConsumer for reporting to 147239462Sdim/// the user. DiagnosticsEngine is tied to one translation unit and one 148239462Sdim/// SourceManager. 149234353Sdimclass DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { 150193326Sedpublic: 151341825Sdim /// The level of the diagnostic, after it has been through mapping. 152193326Sed enum Level { 153218893Sdim Ignored = DiagnosticIDs::Ignored, 154218893Sdim Note = DiagnosticIDs::Note, 155276479Sdim Remark = DiagnosticIDs::Remark, 156218893Sdim Warning = DiagnosticIDs::Warning, 157218893Sdim Error = DiagnosticIDs::Error, 158218893Sdim Fatal = DiagnosticIDs::Fatal 159193326Sed }; 160198092Srdivacky 161193326Sed enum ArgumentKind { 162341825Sdim /// std::string 163341825Sdim ak_std_string, 164341825Sdim 165341825Sdim /// const char * 166341825Sdim ak_c_string, 167341825Sdim 168341825Sdim /// int 169341825Sdim ak_sint, 170341825Sdim 171341825Sdim /// unsigned 172341825Sdim ak_uint, 173341825Sdim 174341825Sdim /// enum TokenKind : unsigned 175341825Sdim ak_tokenkind, 176341825Sdim 177341825Sdim /// IdentifierInfo 178341825Sdim ak_identifierinfo, 179341825Sdim 180360784Sdim /// address space 181360784Sdim ak_addrspace, 182360784Sdim 183344779Sdim /// Qualifiers 184344779Sdim ak_qual, 185344779Sdim 186341825Sdim /// QualType 187341825Sdim ak_qualtype, 188341825Sdim 189341825Sdim /// DeclarationName 190341825Sdim ak_declarationname, 191341825Sdim 192341825Sdim /// NamedDecl * 193341825Sdim ak_nameddecl, 194341825Sdim 195341825Sdim /// NestedNameSpecifier * 196341825Sdim ak_nestednamespec, 197341825Sdim 198341825Sdim /// DeclContext * 199341825Sdim ak_declcontext, 200341825Sdim 201341825Sdim /// pair<QualType, QualType> 202341825Sdim ak_qualtype_pair, 203341825Sdim 204341825Sdim /// Attr * 205341825Sdim ak_attr 206193326Sed }; 207210299Sed 208341825Sdim /// Represents on argument value, which is a union discriminated 209239462Sdim /// by ArgumentKind, with a value. 210341825Sdim using ArgumentValue = std::pair<ArgumentKind, intptr_t>; 211193326Sed 212198092Srdivackyprivate: 213341825Sdim // Used by __extension__ 214341825Sdim unsigned char AllExtensionsSilenced = 0; 215341825Sdim 216353358Sdim // Treat fatal errors like errors. 217353358Sdim bool FatalsAsError = false; 218341825Sdim 219341825Sdim // Suppress all diagnostics. 220341825Sdim bool SuppressAllDiagnostics = false; 221341825Sdim 222341825Sdim // Elide common types of templates. 223341825Sdim bool ElideType = true; 224341825Sdim 225341825Sdim // Print a tree when comparing templates. 226341825Sdim bool PrintTemplateTree = false; 227341825Sdim 228341825Sdim // Color printing is enabled. 229341825Sdim bool ShowColors = false; 230341825Sdim 231341825Sdim // Which overload candidates to show. 232341825Sdim OverloadsShown ShowOverloads = Ovl_All; 233341825Sdim 234341825Sdim // Cap of # errors emitted, 0 -> no limit. 235341825Sdim unsigned ErrorLimit = 0; 236341825Sdim 237341825Sdim // Cap on depth of template backtrace stack, 0 -> no limit. 238341825Sdim unsigned TemplateBacktraceLimit = 0; 239341825Sdim 240341825Sdim // Cap on depth of constexpr evaluation backtrace stack, 0 -> no limit. 241341825Sdim unsigned ConstexprBacktraceLimit = 0; 242341825Sdim 243234353Sdim IntrusiveRefCntPtr<DiagnosticIDs> Diags; 244243830Sdim IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; 245341825Sdim DiagnosticConsumer *Client = nullptr; 246280031Sdim std::unique_ptr<DiagnosticConsumer> Owner; 247341825Sdim SourceManager *SourceMgr = nullptr; 248218893Sdim 249341825Sdim /// Mapping information for diagnostics. 250218893Sdim /// 251239462Sdim /// Mapping info is packed into four bits per diagnostic. The low three 252276479Sdim /// bits are the mapping (an instance of diag::Severity), or zero if unset. 253239462Sdim /// The high bit is set when the mapping was established as a user mapping. 254239462Sdim /// If the high bit is clear, then the low bits are set to the default 255239462Sdim /// value, and should be mapped with -pedantic, -Werror, etc. 256239462Sdim /// 257218893Sdim /// A new DiagState is created and kept around when diagnostic pragmas modify 258218893Sdim /// the state so that we know what is the diagnostic state at any given 259218893Sdim /// source location. 260218893Sdim class DiagState { 261276479Sdim llvm::DenseMap<unsigned, DiagnosticMapping> DiagMap; 262198092Srdivacky 263212904Sdim public: 264321369Sdim // "Global" configuration state that can actually vary between modules. 265321369Sdim 266341825Sdim // Ignore all warnings: -w 267341825Sdim unsigned IgnoreAllWarnings : 1; 268341825Sdim 269341825Sdim // Enable all warnings. 270341825Sdim unsigned EnableAllWarnings : 1; 271341825Sdim 272341825Sdim // Treat warnings like errors. 273341825Sdim unsigned WarningsAsErrors : 1; 274341825Sdim 275341825Sdim // Treat errors like fatal errors. 276341825Sdim unsigned ErrorsAsFatal : 1; 277341825Sdim 278341825Sdim // Suppress warnings in system headers. 279341825Sdim unsigned SuppressSystemWarnings : 1; 280341825Sdim 281341825Sdim // Map extensions to warnings or errors? 282341825Sdim diag::Severity ExtBehavior = diag::Severity::Ignored; 283341825Sdim 284321369Sdim DiagState() 285321369Sdim : IgnoreAllWarnings(false), EnableAllWarnings(false), 286321369Sdim WarningsAsErrors(false), ErrorsAsFatal(false), 287341825Sdim SuppressSystemWarnings(false) {} 288321369Sdim 289341825Sdim using iterator = llvm::DenseMap<unsigned, DiagnosticMapping>::iterator; 290341825Sdim using const_iterator = 291341825Sdim llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator; 292212904Sdim 293276479Sdim void setMapping(diag::kind Diag, DiagnosticMapping Info) { 294226633Sdim DiagMap[Diag] = Info; 295212904Sdim } 296341825Sdim 297321369Sdim DiagnosticMapping lookupMapping(diag::kind Diag) const { 298321369Sdim return DiagMap.lookup(Diag); 299321369Sdim } 300218893Sdim 301276479Sdim DiagnosticMapping &getOrAddMapping(diag::kind Diag); 302226633Sdim 303226633Sdim const_iterator begin() const { return DiagMap.begin(); } 304226633Sdim const_iterator end() const { return DiagMap.end(); } 305212904Sdim }; 306212904Sdim 307341825Sdim /// Keeps and automatically disposes all DiagStates that we create. 308218893Sdim std::list<DiagState> DiagStates; 309198092Srdivacky 310321369Sdim /// A mapping from files to the diagnostic states for those files. Lazily 311321369Sdim /// built on demand for files in which the diagnostic state has not changed. 312321369Sdim class DiagStateMap { 313321369Sdim public: 314321369Sdim /// Add an initial diagnostic state. 315321369Sdim void appendFirst(DiagState *State); 316341825Sdim 317321369Sdim /// Add a new latest state point. 318321369Sdim void append(SourceManager &SrcMgr, SourceLocation Loc, DiagState *State); 319341825Sdim 320321369Sdim /// Look up the diagnostic state at a given source location. 321321369Sdim DiagState *lookup(SourceManager &SrcMgr, SourceLocation Loc) const; 322341825Sdim 323321369Sdim /// Determine whether this map is empty. 324321369Sdim bool empty() const { return Files.empty(); } 325341825Sdim 326321369Sdim /// Clear out this map. 327321369Sdim void clear() { 328321369Sdim Files.clear(); 329321369Sdim FirstDiagState = CurDiagState = nullptr; 330321369Sdim CurDiagStateLoc = SourceLocation(); 331218893Sdim } 332321369Sdim 333341825Sdim /// Produce a debugging dump of the diagnostic state. 334341825Sdim LLVM_DUMP_METHOD void dump(SourceManager &SrcMgr, 335341825Sdim StringRef DiagName = StringRef()) const; 336341825Sdim 337321369Sdim /// Grab the most-recently-added state point. 338321369Sdim DiagState *getCurDiagState() const { return CurDiagState; } 339341825Sdim 340321369Sdim /// Get the location at which a diagnostic state was last added. 341321369Sdim SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; } 342321369Sdim 343321369Sdim private: 344341825Sdim friend class ASTReader; 345341825Sdim friend class ASTWriter; 346341825Sdim 347341825Sdim /// Represents a point in source where the diagnostic state was 348321369Sdim /// modified because of a pragma. 349321369Sdim /// 350321369Sdim /// 'Loc' can be null if the point represents the diagnostic state 351321369Sdim /// modifications done through the command-line. 352321369Sdim struct DiagStatePoint { 353321369Sdim DiagState *State; 354321369Sdim unsigned Offset; 355341825Sdim 356321369Sdim DiagStatePoint(DiagState *State, unsigned Offset) 357341825Sdim : State(State), Offset(Offset) {} 358321369Sdim }; 359321369Sdim 360321369Sdim /// Description of the diagnostic states and state transitions for a 361321369Sdim /// particular FileID. 362321369Sdim struct File { 363321369Sdim /// The diagnostic state for the parent file. This is strictly redundant, 364321369Sdim /// as looking up the DecomposedIncludedLoc for the FileID in the Files 365321369Sdim /// map would give us this, but we cache it here for performance. 366321369Sdim File *Parent = nullptr; 367341825Sdim 368321369Sdim /// The offset of this file within its parent. 369321369Sdim unsigned ParentOffset = 0; 370341825Sdim 371321369Sdim /// Whether this file has any local (not imported from an AST file) 372321369Sdim /// diagnostic state transitions. 373321369Sdim bool HasLocalTransitions = false; 374341825Sdim 375321369Sdim /// The points within the file where the state changes. There will always 376321369Sdim /// be at least one of these (the state on entry to the file). 377321369Sdim llvm::SmallVector<DiagStatePoint, 4> StateTransitions; 378321369Sdim 379321369Sdim DiagState *lookup(unsigned Offset) const; 380321369Sdim }; 381321369Sdim 382321369Sdim /// The diagnostic states for each file. 383321369Sdim mutable std::map<FileID, File> Files; 384321369Sdim 385321369Sdim /// The initial diagnostic state. 386321369Sdim DiagState *FirstDiagState; 387341825Sdim 388321369Sdim /// The current diagnostic state. 389321369Sdim DiagState *CurDiagState; 390341825Sdim 391321369Sdim /// The location at which the current diagnostic state was established. 392321369Sdim SourceLocation CurDiagStateLoc; 393321369Sdim 394321369Sdim /// Get the diagnostic state information for a file. 395321369Sdim File *getFile(SourceManager &SrcMgr, FileID ID) const; 396218893Sdim }; 397218893Sdim 398321369Sdim DiagStateMap DiagStatesByLoc; 399218893Sdim 400341825Sdim /// Keeps the DiagState that was active during each diagnostic 'push' 401218893Sdim /// so we can get back at it when we 'pop'. 402218893Sdim std::vector<DiagState *> DiagStateOnPushStack; 403218893Sdim 404218893Sdim DiagState *GetCurDiagState() const { 405321369Sdim return DiagStatesByLoc.getCurDiagState(); 406218893Sdim } 407218893Sdim 408321369Sdim void PushDiagStatePoint(DiagState *State, SourceLocation L); 409218893Sdim 410341825Sdim /// Finds the DiagStatePoint that contains the diagnostic state of 411218893Sdim /// the given source location. 412321369Sdim DiagState *GetDiagStateForLoc(SourceLocation Loc) const { 413321369Sdim return SourceMgr ? DiagStatesByLoc.lookup(*SourceMgr, Loc) 414321369Sdim : DiagStatesByLoc.getCurDiagState(); 415321369Sdim } 416218893Sdim 417341825Sdim /// Sticky flag set to \c true when an error is emitted. 418193326Sed bool ErrorOccurred; 419239462Sdim 420341825Sdim /// Sticky flag set to \c true when an "uncompilable error" occurs. 421249423Sdim /// I.e. an error that was not upgraded from a warning by -Werror. 422249423Sdim bool UncompilableErrorOccurred; 423249423Sdim 424341825Sdim /// Sticky flag set to \c true when a fatal error is emitted. 425193326Sed bool FatalErrorOccurred; 426198092Srdivacky 427341825Sdim /// Indicates that an unrecoverable error has occurred. 428224145Sdim bool UnrecoverableErrorOccurred; 429341825Sdim 430341825Sdim /// Counts for DiagnosticErrorTrap to check whether an error occurred 431224145Sdim /// during a parsing section, e.g. during parsing a function. 432226633Sdim unsigned TrapNumErrorsOccurred; 433226633Sdim unsigned TrapNumUnrecoverableErrorsOccurred; 434224145Sdim 435341825Sdim /// The level of the last diagnostic emitted. 436239462Sdim /// 437239462Sdim /// This is used to emit continuation diagnostics with the same level as the 438193326Sed /// diagnostic that they follow. 439218893Sdim DiagnosticIDs::Level LastDiagLevel; 440193326Sed 441341825Sdim /// Number of warnings reported 442341825Sdim unsigned NumWarnings; 443193326Sed 444341825Sdim /// Number of errors reported 445341825Sdim unsigned NumErrors; 446341825Sdim 447341825Sdim /// A function pointer that converts an opaque diagnostic 448239462Sdim /// argument to a strings. 449198398Srdivacky /// 450239462Sdim /// This takes the modifiers and argument that was present in the diagnostic. 451239462Sdim /// 452276479Sdim /// The PrevArgs array indicates the previous arguments formatted for this 453276479Sdim /// diagnostic. Implementations of this function can use this information to 454276479Sdim /// avoid redundancy across arguments. 455198398Srdivacky /// 456193326Sed /// This is a hack to avoid a layering violation between libbasic and libsema. 457341825Sdim using ArgToStringFnTy = void (*)( 458224145Sdim ArgumentKind Kind, intptr_t Val, 459276479Sdim StringRef Modifier, StringRef Argument, 460276479Sdim ArrayRef<ArgumentValue> PrevArgs, 461226633Sdim SmallVectorImpl<char> &Output, 462224145Sdim void *Cookie, 463234353Sdim ArrayRef<intptr_t> QualTypeVals); 464341825Sdim 465341825Sdim void *ArgToStringCookie = nullptr; 466193326Sed ArgToStringFnTy ArgToStringFn; 467206084Srdivacky 468341825Sdim /// ID of the "delayed" diagnostic, which is a (typically 469206084Srdivacky /// fatal) diagnostic that had to be delayed because it was found 470206084Srdivacky /// while emitting another diagnostic. 471206084Srdivacky unsigned DelayedDiagID; 472206084Srdivacky 473341825Sdim /// First string argument for the delayed diagnostic. 474206084Srdivacky std::string DelayedDiagArg1; 475206084Srdivacky 476341825Sdim /// Second string argument for the delayed diagnostic. 477206084Srdivacky std::string DelayedDiagArg2; 478206084Srdivacky 479360784Sdim /// Third string argument for the delayed diagnostic. 480360784Sdim std::string DelayedDiagArg3; 481360784Sdim 482341825Sdim /// Optional flag value. 483276479Sdim /// 484276479Sdim /// Some flags accept values, for instance: -Wframe-larger-than=<value> and 485276479Sdim /// -Rpass=<value>. The content of this string is emitted after the flag name 486276479Sdim /// and '='. 487276479Sdim std::string FlagValue; 488276479Sdim 489193326Sedpublic: 490314564Sdim explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags, 491341825Sdim IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, 492314564Sdim DiagnosticConsumer *client = nullptr, 493314564Sdim bool ShouldOwnClient = true); 494314564Sdim DiagnosticsEngine(const DiagnosticsEngine &) = delete; 495314564Sdim DiagnosticsEngine &operator=(const DiagnosticsEngine &) = delete; 496226633Sdim ~DiagnosticsEngine(); 497198092Srdivacky 498344779Sdim LLVM_DUMP_METHOD void dump() const; 499344779Sdim LLVM_DUMP_METHOD void dump(StringRef DiagName) const; 500341825Sdim 501234353Sdim const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const { 502218893Sdim return Diags; 503218893Sdim } 504218893Sdim 505341825Sdim /// Retrieve the diagnostic options. 506243830Sdim DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; } 507243830Sdim 508341825Sdim using diag_mapping_range = llvm::iterator_range<DiagState::const_iterator>; 509276479Sdim 510341825Sdim /// Get the current set of diagnostic mappings. 511276479Sdim diag_mapping_range getDiagnosticMappings() const { 512276479Sdim const DiagState &DS = *GetCurDiagState(); 513276479Sdim return diag_mapping_range(DS.begin(), DS.end()); 514276479Sdim } 515276479Sdim 516226633Sdim DiagnosticConsumer *getClient() { return Client; } 517226633Sdim const DiagnosticConsumer *getClient() const { return Client; } 518218893Sdim 519341825Sdim /// Determine whether this \c DiagnosticsEngine object own its client. 520280031Sdim bool ownsClient() const { return Owner != nullptr; } 521280031Sdim 522341825Sdim /// Return the current diagnostic client along with ownership of that 523218893Sdim /// client. 524280031Sdim std::unique_ptr<DiagnosticConsumer> takeClient() { return std::move(Owner); } 525218893Sdim 526276479Sdim bool hasSourceManager() const { return SourceMgr != nullptr; } 527341825Sdim 528218893Sdim SourceManager &getSourceManager() const { 529218893Sdim assert(SourceMgr && "SourceManager not set!"); 530218893Sdim return *SourceMgr; 531218893Sdim } 532341825Sdim 533321369Sdim void setSourceManager(SourceManager *SrcMgr) { 534321369Sdim assert(DiagStatesByLoc.empty() && 535321369Sdim "Leftover diag state from a different SourceManager."); 536321369Sdim SourceMgr = SrcMgr; 537321369Sdim } 538218893Sdim 539193326Sed //===--------------------------------------------------------------------===// 540226633Sdim // DiagnosticsEngine characterization methods, used by a client to customize 541226633Sdim // how diagnostics are emitted. 542193326Sed // 543198092Srdivacky 544341825Sdim /// Copies the current DiagMappings and pushes the new copy 545198092Srdivacky /// onto the top of the stack. 546218893Sdim void pushMappings(SourceLocation Loc); 547198092Srdivacky 548341825Sdim /// Pops the current DiagMappings off the top of the stack, 549239462Sdim /// causing the new top of the stack to be the active mappings. 550239462Sdim /// 551239462Sdim /// \returns \c true if the pop happens, \c false if there is only one 552239462Sdim /// DiagMapping on the stack. 553218893Sdim bool popMappings(SourceLocation Loc); 554198092Srdivacky 555341825Sdim /// Set the diagnostic client associated with this diagnostic object. 556212904Sdim /// 557218893Sdim /// \param ShouldOwnClient true if the diagnostic object should take 558218893Sdim /// ownership of \c client. 559226633Sdim void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true); 560193326Sed 561341825Sdim /// Specify a limit for the number of errors we should 562239462Sdim /// emit before giving up. 563239462Sdim /// 564239462Sdim /// Zero disables the limit. 565207619Srdivacky void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; } 566341825Sdim 567341825Sdim /// Specify the maximum number of template instantiation 568207619Srdivacky /// notes to emit along with a given diagnostic. 569207619Srdivacky void setTemplateBacktraceLimit(unsigned Limit) { 570207619Srdivacky TemplateBacktraceLimit = Limit; 571207619Srdivacky } 572234353Sdim 573341825Sdim /// Retrieve the maximum number of template instantiation 574234353Sdim /// notes to emit along with a given diagnostic. 575207619Srdivacky unsigned getTemplateBacktraceLimit() const { 576207619Srdivacky return TemplateBacktraceLimit; 577207619Srdivacky } 578234353Sdim 579341825Sdim /// Specify the maximum number of constexpr evaluation 580234353Sdim /// notes to emit along with a given diagnostic. 581234353Sdim void setConstexprBacktraceLimit(unsigned Limit) { 582234353Sdim ConstexprBacktraceLimit = Limit; 583234353Sdim } 584234353Sdim 585341825Sdim /// Retrieve the maximum number of constexpr evaluation 586234353Sdim /// notes to emit along with a given diagnostic. 587234353Sdim unsigned getConstexprBacktraceLimit() const { 588234353Sdim return ConstexprBacktraceLimit; 589234353Sdim } 590234353Sdim 591341825Sdim /// When set to true, any unmapped warnings are ignored. 592239462Sdim /// 593239462Sdim /// If this and WarningsAsErrors are both set, then this one wins. 594321369Sdim void setIgnoreAllWarnings(bool Val) { 595321369Sdim GetCurDiagState()->IgnoreAllWarnings = Val; 596321369Sdim } 597321369Sdim bool getIgnoreAllWarnings() const { 598321369Sdim return GetCurDiagState()->IgnoreAllWarnings; 599321369Sdim } 600198092Srdivacky 601341825Sdim /// When set to true, any unmapped ignored warnings are no longer 602239462Sdim /// ignored. 603239462Sdim /// 604239462Sdim /// If this and IgnoreAllWarnings are both set, then that one wins. 605321369Sdim void setEnableAllWarnings(bool Val) { 606321369Sdim GetCurDiagState()->EnableAllWarnings = Val; 607321369Sdim } 608321369Sdim bool getEnableAllWarnings() const { 609321369Sdim return GetCurDiagState()->EnableAllWarnings; 610321369Sdim } 611249423Sdim 612341825Sdim /// When set to true, any warnings reported are issued as errors. 613321369Sdim void setWarningsAsErrors(bool Val) { 614321369Sdim GetCurDiagState()->WarningsAsErrors = Val; 615321369Sdim } 616321369Sdim bool getWarningsAsErrors() const { 617321369Sdim return GetCurDiagState()->WarningsAsErrors; 618321369Sdim } 619198092Srdivacky 620341825Sdim /// When set to true, any error reported is made a fatal error. 621321369Sdim void setErrorsAsFatal(bool Val) { GetCurDiagState()->ErrorsAsFatal = Val; } 622321369Sdim bool getErrorsAsFatal() const { return GetCurDiagState()->ErrorsAsFatal; } 623201361Srdivacky 624353358Sdim /// \brief When set to true, any fatal error reported is made an error. 625353358Sdim /// 626353358Sdim /// This setting takes precedence over the setErrorsAsFatal setting above. 627353358Sdim void setFatalsAsError(bool Val) { FatalsAsError = Val; } 628353358Sdim bool getFatalsAsError() const { return FatalsAsError; } 629309124Sdim 630341825Sdim /// When set to true mask warnings that come from system headers. 631321369Sdim void setSuppressSystemWarnings(bool Val) { 632321369Sdim GetCurDiagState()->SuppressSystemWarnings = Val; 633321369Sdim } 634321369Sdim bool getSuppressSystemWarnings() const { 635321369Sdim return GetCurDiagState()->SuppressSystemWarnings; 636321369Sdim } 637193326Sed 638341825Sdim /// Suppress all diagnostics, to silence the front end when we 639198092Srdivacky /// know that we don't want any more diagnostics to be passed along to the 640198092Srdivacky /// client 641360784Sdim void setSuppressAllDiagnostics(bool Val) { SuppressAllDiagnostics = Val; } 642198092Srdivacky bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; } 643239462Sdim 644341825Sdim /// Set type eliding, to skip outputting same types occurring in 645239462Sdim /// template types. 646360784Sdim void setElideType(bool Val) { ElideType = Val; } 647239462Sdim bool getElideType() { return ElideType; } 648341825Sdim 649341825Sdim /// Set tree printing, to outputting the template difference in a 650239462Sdim /// tree format. 651360784Sdim void setPrintTemplateTree(bool Val) { PrintTemplateTree = Val; } 652239462Sdim bool getPrintTemplateTree() { return PrintTemplateTree; } 653341825Sdim 654341825Sdim /// Set color printing, so the type diffing will inject color markers 655239462Sdim /// into the output. 656360784Sdim void setShowColors(bool Val) { ShowColors = Val; } 657239462Sdim bool getShowColors() { return ShowColors; } 658239462Sdim 659341825Sdim /// Specify which overload candidates to show when overload resolution 660239462Sdim /// fails. 661239462Sdim /// 662239462Sdim /// By default, we show all candidates. 663210299Sed void setShowOverloads(OverloadsShown Val) { 664210299Sed ShowOverloads = Val; 665210299Sed } 666210299Sed OverloadsShown getShowOverloads() const { return ShowOverloads; } 667341825Sdim 668341825Sdim /// Pretend that the last diagnostic issued was ignored, so any 669327952Sdim /// subsequent notes will be suppressed, or restore a prior ignoring 670327952Sdim /// state after ignoring some diagnostics and their notes, possibly in 671327952Sdim /// the middle of another diagnostic. 672239462Sdim /// 673239462Sdim /// This can be used by clients who suppress diagnostics themselves. 674360784Sdim void setLastDiagnosticIgnored(bool Ignored) { 675243830Sdim if (LastDiagLevel == DiagnosticIDs::Fatal) 676243830Sdim FatalErrorOccurred = true; 677327952Sdim LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning; 678198092Srdivacky } 679261991Sdim 680341825Sdim /// Determine whether the previous diagnostic was ignored. This can 681261991Sdim /// be used by clients that want to determine whether notes attached to a 682261991Sdim /// diagnostic will be suppressed. 683261991Sdim bool isLastDiagnosticIgnored() const { 684261991Sdim return LastDiagLevel == DiagnosticIDs::Ignored; 685261991Sdim } 686261991Sdim 687341825Sdim /// Controls whether otherwise-unmapped extension diagnostics are 688321369Sdim /// mapped onto ignore/warning/error. 689239462Sdim /// 690239462Sdim /// This corresponds to the GCC -pedantic and -pedantic-errors option. 691321369Sdim void setExtensionHandlingBehavior(diag::Severity H) { 692321369Sdim GetCurDiagState()->ExtBehavior = H; 693321369Sdim } 694321369Sdim diag::Severity getExtensionHandlingBehavior() const { 695321369Sdim return GetCurDiagState()->ExtBehavior; 696321369Sdim } 697198092Srdivacky 698341825Sdim /// Counter bumped when an __extension__ block is/ encountered. 699239462Sdim /// 700239462Sdim /// When non-zero, all extension diagnostics are entirely silenced, no 701239462Sdim /// matter how they are mapped. 702193326Sed void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; } 703193326Sed void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; } 704198092Srdivacky bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; } 705198092Srdivacky 706341825Sdim /// This allows the client to specify that certain warnings are 707239462Sdim /// ignored. 708218893Sdim /// 709239462Sdim /// Notes can never be mapped, errors can only be mapped to fatal, and 710239462Sdim /// WARNINGs and EXTENSIONs can be mapped arbitrarily. 711239462Sdim /// 712218893Sdim /// \param Loc The source location that this change of diagnostic state should 713218893Sdim /// take affect. It can be null if we are setting the latest state. 714276479Sdim void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc); 715198092Srdivacky 716341825Sdim /// Change an entire diagnostic group (e.g. "unknown-pragmas") to 717239462Sdim /// have the specified mapping. 718218893Sdim /// 719239462Sdim /// \returns true (and ignores the request) if "Group" was unknown, false 720239462Sdim /// otherwise. 721239462Sdim /// 722276479Sdim /// \param Flavor The flavor of group to affect. -Rfoo does not affect the 723276479Sdim /// state of the -Wfoo group and vice versa. 724276479Sdim /// 725239462Sdim /// \param Loc The source location that this change of diagnostic state should 726218893Sdim /// take affect. It can be null if we are setting the state from command-line. 727276479Sdim bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group, 728276479Sdim diag::Severity Map, 729276479Sdim SourceLocation Loc = SourceLocation()); 730193326Sed 731341825Sdim /// Set the warning-as-error flag for the given diagnostic group. 732226633Sdim /// 733239462Sdim /// This function always only operates on the current diagnostic state. 734239462Sdim /// 735226633Sdim /// \returns True if the given group is unknown, false otherwise. 736226633Sdim bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled); 737226633Sdim 738341825Sdim /// Set the error-as-fatal flag for the given diagnostic group. 739226633Sdim /// 740239462Sdim /// This function always only operates on the current diagnostic state. 741239462Sdim /// 742226633Sdim /// \returns True if the given group is unknown, false otherwise. 743226633Sdim bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled); 744226633Sdim 745341825Sdim /// Add the specified mapping to all diagnostics of the specified 746276479Sdim /// flavor. 747239462Sdim /// 748239462Sdim /// Mainly to be used by -Wno-everything to disable all warnings but allow 749239462Sdim /// subsequent -W options to enable specific warnings. 750276479Sdim void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map, 751276479Sdim SourceLocation Loc = SourceLocation()); 752234353Sdim 753193326Sed bool hasErrorOccurred() const { return ErrorOccurred; } 754249423Sdim 755341825Sdim /// Errors that actually prevent compilation, not those that are 756249423Sdim /// upgraded from a warning by -Werror. 757249423Sdim bool hasUncompilableErrorOccurred() const { 758249423Sdim return UncompilableErrorOccurred; 759249423Sdim } 760193326Sed bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } 761341825Sdim 762341825Sdim /// Determine whether any kind of unrecoverable error has occurred. 763224145Sdim bool hasUnrecoverableErrorOccurred() const { 764224145Sdim return FatalErrorOccurred || UnrecoverableErrorOccurred; 765224145Sdim } 766341825Sdim 767207619Srdivacky unsigned getNumWarnings() const { return NumWarnings; } 768198092Srdivacky 769212904Sdim void setNumWarnings(unsigned NumWarnings) { 770212904Sdim this->NumWarnings = NumWarnings; 771212904Sdim } 772212904Sdim 773341825Sdim /// Return an ID for a diagnostic with the specified format string and 774276479Sdim /// level. 775239462Sdim /// 776249423Sdim /// If this is the first request for this diagnostic, it is registered and 777239462Sdim /// created, otherwise the existing ID is returned. 778276479Sdim /// 779276479Sdim /// \param FormatString A fixed diagnostic format string that will be hashed 780276479Sdim /// and mapped to a unique DiagID. 781276479Sdim template <unsigned N> 782276479Sdim unsigned getCustomDiagID(Level L, const char (&FormatString)[N]) { 783276479Sdim return Diags->getCustomDiagID((DiagnosticIDs::Level)L, 784276479Sdim StringRef(FormatString, N - 1)); 785218893Sdim } 786198092Srdivacky 787341825Sdim /// Converts a diagnostic argument (as an intptr_t) into the string 788239462Sdim /// that represents it. 789193326Sed void ConvertArgToString(ArgumentKind Kind, intptr_t Val, 790276479Sdim StringRef Modifier, StringRef Argument, 791276479Sdim ArrayRef<ArgumentValue> PrevArgs, 792226633Sdim SmallVectorImpl<char> &Output, 793243830Sdim ArrayRef<intptr_t> QualTypeVals) const { 794276479Sdim ArgToStringFn(Kind, Val, Modifier, Argument, PrevArgs, Output, 795276479Sdim ArgToStringCookie, QualTypeVals); 796193326Sed } 797198092Srdivacky 798193326Sed void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { 799193326Sed ArgToStringFn = Fn; 800193326Sed ArgToStringCookie = Cookie; 801193326Sed } 802198092Srdivacky 803341825Sdim /// Note that the prior diagnostic was emitted by some other 804249423Sdim /// \c DiagnosticsEngine, and we may be attaching a note to that diagnostic. 805249423Sdim void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) { 806249423Sdim LastDiagLevel = Other.LastDiagLevel; 807249423Sdim } 808249423Sdim 809341825Sdim /// Reset the state of the diagnostic object to its initial 810212904Sdim /// configuration. 811212904Sdim void Reset(); 812341825Sdim 813193326Sed //===--------------------------------------------------------------------===// 814226633Sdim // DiagnosticsEngine classification and reporting interfaces. 815193326Sed // 816193326Sed 817341825Sdim /// Determine whether the diagnostic is known to be ignored. 818276479Sdim /// 819276479Sdim /// This can be used to opportunistically avoid expensive checks when it's 820276479Sdim /// known for certain that the diagnostic has been suppressed at the 821276479Sdim /// specified location \p Loc. 822276479Sdim /// 823276479Sdim /// \param Loc The source location we are interested in finding out the 824276479Sdim /// diagnostic state. Can be null in order to query the latest state. 825276479Sdim bool isIgnored(unsigned DiagID, SourceLocation Loc) const { 826276479Sdim return Diags->getDiagnosticSeverity(DiagID, Loc, *this) == 827276479Sdim diag::Severity::Ignored; 828276479Sdim } 829276479Sdim 830341825Sdim /// Based on the way the client configured the DiagnosticsEngine 831218893Sdim /// object, classify the specified diagnostic ID into a Level, consumable by 832226633Sdim /// the DiagnosticConsumer. 833193326Sed /// 834276479Sdim /// To preserve invariant assumptions, this function should not be used to 835276479Sdim /// influence parse or semantic analysis actions. Instead consider using 836276479Sdim /// \c isIgnored(). 837276479Sdim /// 838218893Sdim /// \param Loc The source location we are interested in finding out the 839218893Sdim /// diagnostic state. Can be null in order to query the latest state. 840226633Sdim Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const { 841226633Sdim return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this); 842207619Srdivacky } 843198092Srdivacky 844341825Sdim /// Issue the message to the client. 845239462Sdim /// 846239462Sdim /// This actually returns an instance of DiagnosticBuilder which emits the 847239462Sdim /// diagnostics (through @c ProcessDiag) when it is destroyed. 848239462Sdim /// 849239462Sdim /// \param DiagID A member of the @c diag::kind enum. 850239462Sdim /// \param Loc Represents the source location associated with the diagnostic, 851193326Sed /// which can be an invalid location if no position information is available. 852239462Sdim inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID); 853199482Srdivacky inline DiagnosticBuilder Report(unsigned DiagID); 854193326Sed 855223017Sdim void Report(const StoredDiagnostic &storedDiag); 856223017Sdim 857341825Sdim /// Determine whethere there is already a diagnostic in flight. 858341825Sdim bool isDiagnosticInFlight() const { 859341825Sdim return CurDiagID != std::numeric_limits<unsigned>::max(); 860341825Sdim } 861206084Srdivacky 862341825Sdim /// Set the "delayed" diagnostic that will be emitted once 863206084Srdivacky /// the current diagnostic completes. 864206084Srdivacky /// 865206084Srdivacky /// If a diagnostic is already in-flight but the front end must 866206084Srdivacky /// report a problem (e.g., with an inconsistent file system 867206084Srdivacky /// state), this routine sets a "delayed" diagnostic that will be 868206084Srdivacky /// emitted after the current diagnostic completes. This should 869206084Srdivacky /// only be used for fatal errors detected at inconvenient 870206084Srdivacky /// times. If emitting a delayed diagnostic causes a second delayed 871206084Srdivacky /// diagnostic to be introduced, that second delayed diagnostic 872206084Srdivacky /// will be ignored. 873206084Srdivacky /// 874206084Srdivacky /// \param DiagID The ID of the diagnostic being delayed. 875206084Srdivacky /// 876206084Srdivacky /// \param Arg1 A string argument that will be provided to the 877206084Srdivacky /// diagnostic. A copy of this string will be stored in the 878226633Sdim /// DiagnosticsEngine object itself. 879206084Srdivacky /// 880206084Srdivacky /// \param Arg2 A string argument that will be provided to the 881206084Srdivacky /// diagnostic. A copy of this string will be stored in the 882226633Sdim /// DiagnosticsEngine object itself. 883360784Sdim /// 884360784Sdim /// \param Arg3 A string argument that will be provided to the 885360784Sdim /// diagnostic. A copy of this string will be stored in the 886360784Sdim /// DiagnosticsEngine object itself. 887226633Sdim void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "", 888360784Sdim StringRef Arg2 = "", StringRef Arg3 = ""); 889198092Srdivacky 890341825Sdim /// Clear out the current diagnostic. 891341825Sdim void Clear() { CurDiagID = std::numeric_limits<unsigned>::max(); } 892341825Sdim 893341825Sdim /// Return the value associated with this diagnostic flag. 894276479Sdim StringRef getFlagValue() const { return FlagValue; } 895276479Sdim 896193326Sedprivate: 897193326Sed // This is private state used by DiagnosticBuilder. We put it here instead of 898193326Sed // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight 899193326Sed // object. This implementation choice means that we can only have one 900193326Sed // diagnostic "in flight" at a time, but this seems to be a reasonable 901193326Sed // tradeoff to keep these objects small. Assertions verify that only one 902193326Sed // diagnostic is in flight at a time. 903341825Sdim friend class Diagnostic; 904341825Sdim friend class DiagnosticBuilder; 905341825Sdim friend class DiagnosticErrorTrap; 906218893Sdim friend class DiagnosticIDs; 907218893Sdim friend class PartialDiagnostic; 908341825Sdim 909341825Sdim /// Report the delayed diagnostic. 910341825Sdim void ReportDelayed(); 911341825Sdim 912341825Sdim /// The location of the current diagnostic that is in flight. 913218893Sdim SourceLocation CurDiagLoc; 914198092Srdivacky 915341825Sdim /// The ID of the current diagnostic that is in flight. 916239462Sdim /// 917341825Sdim /// This is set to std::numeric_limits<unsigned>::max() when there is no 918341825Sdim /// diagnostic in flight. 919193326Sed unsigned CurDiagID; 920193326Sed 921193326Sed enum { 922341825Sdim /// The maximum number of arguments we can hold. 923239462Sdim /// 924239462Sdim /// We currently only support up to 10 arguments (%0-%9). A single 925239462Sdim /// diagnostic with more than that almost certainly has to be simplified 926239462Sdim /// anyway. 927234353Sdim MaxArguments = 10, 928193326Sed }; 929198092Srdivacky 930341825Sdim /// The number of entries in Arguments. 931193326Sed signed char NumDiagArgs; 932193326Sed 933341825Sdim /// Specifies whether an argument is in DiagArgumentsStr or 934239462Sdim /// in DiagArguments. 935239462Sdim /// 936239462Sdim /// This is an array of ArgumentKind::ArgumentKind enum values, one for each 937239462Sdim /// argument. 938193326Sed unsigned char DiagArgumentsKind[MaxArguments]; 939198092Srdivacky 940341825Sdim /// Holds the values of each string argument for the current 941239462Sdim /// diagnostic. 942239462Sdim /// 943239462Sdim /// This is only used when the corresponding ArgumentKind is ak_std_string. 944193326Sed std::string DiagArgumentsStr[MaxArguments]; 945193326Sed 946341825Sdim /// The values for the various substitution positions. 947239462Sdim /// 948239462Sdim /// This is used when the argument is not an std::string. The specific 949239462Sdim /// value is mangled into an intptr_t and the interpretation depends on 950239462Sdim /// exactly what sort of argument kind it is. 951193326Sed intptr_t DiagArgumentsVal[MaxArguments]; 952198092Srdivacky 953341825Sdim /// The list of ranges added to this diagnostic. 954276479Sdim SmallVector<CharSourceRange, 8> DiagRanges; 955198092Srdivacky 956341825Sdim /// If valid, provides a hint with some code to insert, remove, 957234353Sdim /// or modify at a particular position. 958276479Sdim SmallVector<FixItHint, 8> DiagFixItHints; 959193326Sed 960276479Sdim DiagnosticMapping makeUserMapping(diag::Severity Map, SourceLocation L) { 961234353Sdim bool isPragma = L.isValid(); 962276479Sdim DiagnosticMapping Mapping = 963276479Sdim DiagnosticMapping::Make(Map, /*IsUser=*/true, isPragma); 964193326Sed 965234353Sdim // If this is a pragma mapping, then set the diagnostic mapping flags so 966234353Sdim // that we override command line options. 967234353Sdim if (isPragma) { 968276479Sdim Mapping.setNoWarningAsError(true); 969276479Sdim Mapping.setNoErrorAsFatal(true); 970234353Sdim } 971234353Sdim 972276479Sdim return Mapping; 973234353Sdim } 974234353Sdim 975341825Sdim /// Used to report a diagnostic that is finally fully formed. 976194179Sed /// 977239462Sdim /// \returns true if the diagnostic was emitted, false if it was suppressed. 978218893Sdim bool ProcessDiag() { 979218893Sdim return Diags->ProcessDiag(*this); 980218893Sdim } 981218893Sdim 982234353Sdim /// @name Diagnostic Emission 983234353Sdim /// @{ 984234353Sdimprotected: 985341825Sdim friend class ASTReader; 986341825Sdim friend class ASTWriter; 987341825Sdim 988234353Sdim // Sema requires access to the following functions because the current design 989234353Sdim // of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to 990234353Sdim // access us directly to ensure we minimize the emitted code for the common 991234353Sdim // Sema::Diag() patterns. 992234353Sdim friend class Sema; 993234353Sdim 994341825Sdim /// Emit the current diagnostic and clear the diagnostic state. 995239462Sdim /// 996239462Sdim /// \param Force Emit the diagnostic regardless of suppression settings. 997239462Sdim bool EmitCurrentDiagnostic(bool Force = false); 998234353Sdim 999234353Sdim unsigned getCurrentDiagID() const { return CurDiagID; } 1000234353Sdim 1001234353Sdim SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; } 1002234353Sdim 1003234353Sdim /// @} 1004193326Sed}; 1005193326Sed 1006341825Sdim/// RAII class that determines when any errors have occurred 1007218893Sdim/// between the time the instance was created and the time it was 1008218893Sdim/// queried. 1009218893Sdimclass DiagnosticErrorTrap { 1010226633Sdim DiagnosticsEngine &Diag; 1011226633Sdim unsigned NumErrors; 1012226633Sdim unsigned NumUnrecoverableErrors; 1013218893Sdim 1014218893Sdimpublic: 1015226633Sdim explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag) 1016341825Sdim : Diag(Diag) { reset(); } 1017218893Sdim 1018341825Sdim /// Determine whether any errors have occurred since this 1019218893Sdim /// object instance was created. 1020218893Sdim bool hasErrorOccurred() const { 1021226633Sdim return Diag.TrapNumErrorsOccurred > NumErrors; 1022218893Sdim } 1023218893Sdim 1024341825Sdim /// Determine whether any unrecoverable errors have occurred since this 1025224145Sdim /// object instance was created. 1026224145Sdim bool hasUnrecoverableErrorOccurred() const { 1027226633Sdim return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors; 1028224145Sdim } 1029224145Sdim 1030341825Sdim /// Set to initial state of "no errors occurred". 1031224145Sdim void reset() { 1032226633Sdim NumErrors = Diag.TrapNumErrorsOccurred; 1033226633Sdim NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred; 1034224145Sdim } 1035218893Sdim}; 1036218893Sdim 1037193326Sed//===----------------------------------------------------------------------===// 1038193326Sed// DiagnosticBuilder 1039193326Sed//===----------------------------------------------------------------------===// 1040193326Sed 1041341825Sdim/// A little helper class used to produce diagnostics. 1042193326Sed/// 1043239462Sdim/// This is constructed by the DiagnosticsEngine::Report method, and 1044239462Sdim/// allows insertion of extra information (arguments and source ranges) into 1045239462Sdim/// the currently "in flight" diagnostic. When the temporary for the builder 1046239462Sdim/// is destroyed, the diagnostic is issued. 1047239462Sdim/// 1048193326Sed/// Note that many of these will be created as temporary objects (many call 1049193326Sed/// sites), so we want them to be small and we never want their address taken. 1050193326Sed/// This ensures that compilers with somewhat reasonable optimizers will promote 1051193326Sed/// the common fields to registers, eliminating increments of the NumArgs field, 1052193326Sed/// for example. 1053193326Sedclass DiagnosticBuilder { 1054341825Sdim friend class DiagnosticsEngine; 1055341825Sdim friend class PartialDiagnostic; 1056341825Sdim 1057296417Sdim mutable DiagnosticsEngine *DiagObj = nullptr; 1058296417Sdim mutable unsigned NumArgs = 0; 1059198092Srdivacky 1060341825Sdim /// Status variable indicating if this diagnostic is still active. 1061234353Sdim /// 1062234353Sdim // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)), 1063234353Sdim // but LLVM is not currently smart enough to eliminate the null check that 1064234353Sdim // Emit() would end up with if we used that as our status variable. 1065296417Sdim mutable bool IsActive = false; 1066234353Sdim 1067341825Sdim /// Flag indicating that this diagnostic is being emitted via a 1068239462Sdim /// call to ForceEmit. 1069296417Sdim mutable bool IsForceEmit = false; 1070239462Sdim 1071296417Sdim DiagnosticBuilder() = default; 1072239462Sdim 1073226633Sdim explicit DiagnosticBuilder(DiagnosticsEngine *diagObj) 1074296417Sdim : DiagObj(diagObj), IsActive(true) { 1075234353Sdim assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!"); 1076276479Sdim diagObj->DiagRanges.clear(); 1077276479Sdim diagObj->DiagFixItHints.clear(); 1078234353Sdim } 1079193326Sed 1080218893Sdimprotected: 1081234353Sdim void FlushCounts() { 1082234353Sdim DiagObj->NumDiagArgs = NumArgs; 1083193326Sed } 1084193326Sed 1085341825Sdim /// Clear out the current diagnostic. 1086234353Sdim void Clear() const { 1087276479Sdim DiagObj = nullptr; 1088234353Sdim IsActive = false; 1089239462Sdim IsForceEmit = false; 1090234353Sdim } 1091194179Sed 1092341825Sdim /// Determine whether this diagnostic is still active. 1093234353Sdim bool isActive() const { return IsActive; } 1094194179Sed 1095341825Sdim /// Force the diagnostic builder to emit the diagnostic now. 1096193326Sed /// 1097193326Sed /// Once this function has been called, the DiagnosticBuilder object 1098193326Sed /// should not be used again before it is destroyed. 1099194179Sed /// 1100194179Sed /// \returns true if a diagnostic was emitted, false if the 1101194179Sed /// diagnostic was suppressed. 1102234353Sdim bool Emit() { 1103234353Sdim // If this diagnostic is inactive, then its soul was stolen by the copy ctor 1104234353Sdim // (or by a subclass, as in SemaDiagnosticBuilder). 1105234353Sdim if (!isActive()) return false; 1106193326Sed 1107234353Sdim // When emitting diagnostics, we set the final argument count into 1108234353Sdim // the DiagnosticsEngine object. 1109234353Sdim FlushCounts(); 1110198092Srdivacky 1111234353Sdim // Process the diagnostic. 1112239462Sdim bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit); 1113203955Srdivacky 1114234353Sdim // This diagnostic is dead. 1115234353Sdim Clear(); 1116234353Sdim 1117234353Sdim return Result; 1118218893Sdim } 1119341825Sdim 1120234353Sdimpublic: 1121234353Sdim /// Copy constructor. When copied, this "takes" the diagnostic info from the 1122234353Sdim /// input and neuters it. 1123234353Sdim DiagnosticBuilder(const DiagnosticBuilder &D) { 1124234353Sdim DiagObj = D.DiagObj; 1125234353Sdim IsActive = D.IsActive; 1126239462Sdim IsForceEmit = D.IsForceEmit; 1127234353Sdim D.Clear(); 1128234353Sdim NumArgs = D.NumArgs; 1129234353Sdim } 1130234353Sdim 1131314564Sdim DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete; 1132314564Sdim 1133341825Sdim /// Emits the diagnostic. 1134314564Sdim ~DiagnosticBuilder() { 1135314564Sdim Emit(); 1136314564Sdim } 1137314564Sdim 1138341825Sdim /// Forces the diagnostic to be emitted. 1139239462Sdim const DiagnosticBuilder &setForceEmit() const { 1140239462Sdim IsForceEmit = true; 1141239462Sdim return *this; 1142239462Sdim } 1143239462Sdim 1144341825Sdim /// Conversion of DiagnosticBuilder to bool always returns \c true. 1145239462Sdim /// 1146239462Sdim /// This allows is to be used in boolean error contexts (where \c true is 1147239462Sdim /// used to indicate that an error has occurred), like: 1148239462Sdim /// \code 1149193326Sed /// return Diag(...); 1150239462Sdim /// \endcode 1151193326Sed operator bool() const { return true; } 1152193326Sed 1153226633Sdim void AddString(StringRef S) const { 1154234353Sdim assert(isActive() && "Clients must not add to cleared diagnostic!"); 1155226633Sdim assert(NumArgs < DiagnosticsEngine::MaxArguments && 1156193326Sed "Too many arguments to diagnostic!"); 1157234353Sdim DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string; 1158234353Sdim DiagObj->DiagArgumentsStr[NumArgs++] = S; 1159193326Sed } 1160198092Srdivacky 1161226633Sdim void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const { 1162234353Sdim assert(isActive() && "Clients must not add to cleared diagnostic!"); 1163226633Sdim assert(NumArgs < DiagnosticsEngine::MaxArguments && 1164193326Sed "Too many arguments to diagnostic!"); 1165234353Sdim DiagObj->DiagArgumentsKind[NumArgs] = Kind; 1166234353Sdim DiagObj->DiagArgumentsVal[NumArgs++] = V; 1167193326Sed } 1168198092Srdivacky 1169210299Sed void AddSourceRange(const CharSourceRange &R) const { 1170234353Sdim assert(isActive() && "Clients must not add to cleared diagnostic!"); 1171276479Sdim DiagObj->DiagRanges.push_back(R); 1172198092Srdivacky } 1173193326Sed 1174206084Srdivacky void AddFixItHint(const FixItHint &Hint) const { 1175234353Sdim assert(isActive() && "Clients must not add to cleared diagnostic!"); 1176288943Sdim if (!Hint.isNull()) 1177288943Sdim DiagObj->DiagFixItHints.push_back(Hint); 1178193326Sed } 1179243830Sdim 1180276479Sdim void addFlagValue(StringRef V) const { DiagObj->FlagValue = V; } 1181276479Sdim}; 1182261991Sdim 1183276479Sdimstruct AddFlagValue { 1184341825Sdim StringRef Val; 1185341825Sdim 1186276479Sdim explicit AddFlagValue(StringRef V) : Val(V) {} 1187193326Sed}; 1188193326Sed 1189341825Sdim/// Register a value for the flag in the current diagnostic. This 1190276479Sdim/// value will be shown as the suffix "=value" after the flag name. It is 1191276479Sdim/// useful in cases where the diagnostic flag accepts values (e.g., 1192276479Sdim/// -Rpass or -Wframe-larger-than). 1193193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1194276479Sdim const AddFlagValue V) { 1195276479Sdim DB.addFlagValue(V.Val); 1196276479Sdim return DB; 1197276479Sdim} 1198276479Sdim 1199276479Sdiminline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1200226633Sdim StringRef S) { 1201193326Sed DB.AddString(S); 1202193326Sed return DB; 1203193326Sed} 1204193326Sed 1205193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1206193326Sed const char *Str) { 1207193326Sed DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str), 1208226633Sdim DiagnosticsEngine::ak_c_string); 1209193326Sed return DB; 1210193326Sed} 1211193326Sed 1212193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) { 1213226633Sdim DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); 1214193326Sed return DB; 1215193326Sed} 1216193326Sed 1217276479Sdim// We use enable_if here to prevent that this overload is selected for 1218276479Sdim// pointers or other arguments that are implicitly convertible to bool. 1219276479Sdimtemplate <typename T> 1220276479Sdiminline 1221276479Sdimtypename std::enable_if<std::is_same<T, bool>::value, 1222276479Sdim const DiagnosticBuilder &>::type 1223276479Sdimoperator<<(const DiagnosticBuilder &DB, T I) { 1224226633Sdim DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); 1225193326Sed return DB; 1226193326Sed} 1227193326Sed 1228193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1229193326Sed unsigned I) { 1230226633Sdim DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint); 1231193326Sed return DB; 1232193326Sed} 1233193326Sed 1234193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1235276479Sdim tok::TokenKind I) { 1236276479Sdim DB.AddTaggedVal(static_cast<unsigned>(I), DiagnosticsEngine::ak_tokenkind); 1237276479Sdim return DB; 1238276479Sdim} 1239276479Sdim 1240276479Sdiminline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1241193326Sed const IdentifierInfo *II) { 1242193326Sed DB.AddTaggedVal(reinterpret_cast<intptr_t>(II), 1243226633Sdim DiagnosticsEngine::ak_identifierinfo); 1244193326Sed return DB; 1245193326Sed} 1246198092Srdivacky 1247198092Srdivacky// Adds a DeclContext to the diagnostic. The enable_if template magic is here 1248198092Srdivacky// so that we only match those arguments that are (statically) DeclContexts; 1249198092Srdivacky// other arguments that derive from DeclContext (e.g., RecordDecls) will not 1250198092Srdivacky// match. 1251309124Sdimtemplate <typename T> 1252309124Sdiminline typename std::enable_if< 1253309124Sdim std::is_same<typename std::remove_const<T>::type, DeclContext>::value, 1254309124Sdim const DiagnosticBuilder &>::type 1255198092Srdivackyoperator<<(const DiagnosticBuilder &DB, T *DC) { 1256198092Srdivacky DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC), 1257226633Sdim DiagnosticsEngine::ak_declcontext); 1258198092Srdivacky return DB; 1259198092Srdivacky} 1260276479Sdim 1261193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1262296417Sdim SourceRange R) { 1263210299Sed DB.AddSourceRange(CharSourceRange::getTokenRange(R)); 1264193326Sed return DB; 1265193326Sed} 1266193326Sed 1267193326Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1268276479Sdim ArrayRef<SourceRange> Ranges) { 1269296417Sdim for (SourceRange R : Ranges) 1270276479Sdim DB.AddSourceRange(CharSourceRange::getTokenRange(R)); 1271276479Sdim return DB; 1272276479Sdim} 1273276479Sdim 1274276479Sdiminline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1275210299Sed const CharSourceRange &R) { 1276210299Sed DB.AddSourceRange(R); 1277210299Sed return DB; 1278210299Sed} 1279276479Sdim 1280210299Sedinline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1281206084Srdivacky const FixItHint &Hint) { 1282288943Sdim DB.AddFixItHint(Hint); 1283288943Sdim return DB; 1284288943Sdim} 1285288943Sdim 1286288943Sdiminline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1287288943Sdim ArrayRef<FixItHint> Hints) { 1288288943Sdim for (const FixItHint &Hint : Hints) 1289234353Sdim DB.AddFixItHint(Hint); 1290193326Sed return DB; 1291193326Sed} 1292193326Sed 1293288943Sdim/// A nullability kind paired with a bit indicating whether it used a 1294288943Sdim/// context-sensitive keyword. 1295341825Sdimusing DiagNullabilityKind = std::pair<NullabilityKind, bool>; 1296288943Sdim 1297288943Sdimconst DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1298288943Sdim DiagNullabilityKind nullability); 1299288943Sdim 1300226633Sdiminline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc, 1301276479Sdim unsigned DiagID) { 1302341825Sdim assert(CurDiagID == std::numeric_limits<unsigned>::max() && 1303341825Sdim "Multiple diagnostics in flight at once!"); 1304193326Sed CurDiagLoc = Loc; 1305193326Sed CurDiagID = DiagID; 1306276479Sdim FlagValue.clear(); 1307193326Sed return DiagnosticBuilder(this); 1308193326Sed} 1309276479Sdim 1310353358Sdiminline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1311353358Sdim llvm::Error &&E) { 1312353358Sdim DB.AddString(toString(std::move(E))); 1313353358Sdim return DB; 1314353358Sdim} 1315353358Sdim 1316226633Sdiminline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) { 1317218893Sdim return Report(SourceLocation(), DiagID); 1318199482Srdivacky} 1319193326Sed 1320193326Sed//===----------------------------------------------------------------------===// 1321226633Sdim// Diagnostic 1322193326Sed//===----------------------------------------------------------------------===// 1323198092Srdivacky 1324239462Sdim/// A little helper class (which is basically a smart pointer that forwards 1325239462Sdim/// info from DiagnosticsEngine) that allows clients to enquire about the 1326239462Sdim/// currently in-flight diagnostic. 1327226633Sdimclass Diagnostic { 1328226633Sdim const DiagnosticsEngine *DiagObj; 1329226633Sdim StringRef StoredDiagMessage; 1330314564Sdim 1331193326Sedpublic: 1332226633Sdim explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {} 1333226633Sdim Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage) 1334341825Sdim : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {} 1335198092Srdivacky 1336226633Sdim const DiagnosticsEngine *getDiags() const { return DiagObj; } 1337193326Sed unsigned getID() const { return DiagObj->CurDiagID; } 1338218893Sdim const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; } 1339218893Sdim bool hasSourceManager() const { return DiagObj->hasSourceManager(); } 1340218893Sdim SourceManager &getSourceManager() const { return DiagObj->getSourceManager();} 1341198092Srdivacky 1342193326Sed unsigned getNumArgs() const { return DiagObj->NumDiagArgs; } 1343198092Srdivacky 1344341825Sdim /// Return the kind of the specified index. 1345239462Sdim /// 1346239462Sdim /// Based on the kind of argument, the accessors below can be used to get 1347239462Sdim /// the value. 1348239462Sdim /// 1349239462Sdim /// \pre Idx < getNumArgs() 1350226633Sdim DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const { 1351193326Sed assert(Idx < getNumArgs() && "Argument index out of range!"); 1352226633Sdim return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx]; 1353193326Sed } 1354198092Srdivacky 1355341825Sdim /// Return the provided argument string specified by \p Idx. 1356239462Sdim /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string 1357193326Sed const std::string &getArgStdStr(unsigned Idx) const { 1358226633Sdim assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string && 1359193326Sed "invalid argument accessor!"); 1360193326Sed return DiagObj->DiagArgumentsStr[Idx]; 1361193326Sed } 1362198092Srdivacky 1363341825Sdim /// Return the specified C string argument. 1364239462Sdim /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string 1365193326Sed const char *getArgCStr(unsigned Idx) const { 1366226633Sdim assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string && 1367193326Sed "invalid argument accessor!"); 1368193326Sed return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]); 1369193326Sed } 1370198092Srdivacky 1371341825Sdim /// Return the specified signed integer argument. 1372239462Sdim /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint 1373193326Sed int getArgSInt(unsigned Idx) const { 1374226633Sdim assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint && 1375193326Sed "invalid argument accessor!"); 1376193326Sed return (int)DiagObj->DiagArgumentsVal[Idx]; 1377193326Sed } 1378198092Srdivacky 1379341825Sdim /// Return the specified unsigned integer argument. 1380239462Sdim /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint 1381193326Sed unsigned getArgUInt(unsigned Idx) const { 1382226633Sdim assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint && 1383193326Sed "invalid argument accessor!"); 1384193326Sed return (unsigned)DiagObj->DiagArgumentsVal[Idx]; 1385193326Sed } 1386198092Srdivacky 1387341825Sdim /// Return the specified IdentifierInfo argument. 1388239462Sdim /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo 1389193326Sed const IdentifierInfo *getArgIdentifier(unsigned Idx) const { 1390226633Sdim assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo && 1391193326Sed "invalid argument accessor!"); 1392193326Sed return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]); 1393193326Sed } 1394198092Srdivacky 1395341825Sdim /// Return the specified non-string argument in an opaque form. 1396239462Sdim /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string 1397193326Sed intptr_t getRawArg(unsigned Idx) const { 1398226633Sdim assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string && 1399193326Sed "invalid argument accessor!"); 1400193326Sed return DiagObj->DiagArgumentsVal[Idx]; 1401193326Sed } 1402198092Srdivacky 1403341825Sdim /// Return the number of source ranges associated with this diagnostic. 1404193326Sed unsigned getNumRanges() const { 1405276479Sdim return DiagObj->DiagRanges.size(); 1406193326Sed } 1407198092Srdivacky 1408239462Sdim /// \pre Idx < getNumRanges() 1409210299Sed const CharSourceRange &getRange(unsigned Idx) const { 1410276479Sdim assert(Idx < getNumRanges() && "Invalid diagnostic range index!"); 1411203955Srdivacky return DiagObj->DiagRanges[Idx]; 1412193326Sed } 1413198092Srdivacky 1414341825Sdim /// Return an array reference for this diagnostic's ranges. 1415234353Sdim ArrayRef<CharSourceRange> getRanges() const { 1416276479Sdim return DiagObj->DiagRanges; 1417234353Sdim } 1418234353Sdim 1419206084Srdivacky unsigned getNumFixItHints() const { 1420276479Sdim return DiagObj->DiagFixItHints.size(); 1421193326Sed } 1422193326Sed 1423206084Srdivacky const FixItHint &getFixItHint(unsigned Idx) const { 1424234353Sdim assert(Idx < getNumFixItHints() && "Invalid index!"); 1425234353Sdim return DiagObj->DiagFixItHints[Idx]; 1426193326Sed } 1427193326Sed 1428276479Sdim ArrayRef<FixItHint> getFixItHints() const { 1429276479Sdim return DiagObj->DiagFixItHints; 1430193326Sed } 1431193326Sed 1432341825Sdim /// Format this diagnostic into a string, substituting the 1433239462Sdim /// formal arguments into the %0 slots. 1434239462Sdim /// 1435239462Sdim /// The result is appended onto the \p OutStr array. 1436226633Sdim void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const; 1437202379Srdivacky 1438341825Sdim /// Format the given format-string into the output buffer using the 1439239462Sdim /// arguments stored in this diagnostic. 1440202379Srdivacky void FormatDiagnostic(const char *DiagStr, const char *DiagEnd, 1441226633Sdim SmallVectorImpl<char> &OutStr) const; 1442204643Srdivacky}; 1443203955Srdivacky 1444204643Srdivacky/** 1445341825Sdim * Represents a diagnostic in a form that can be retained until its 1446341825Sdim * corresponding source manager is destroyed. 1447204643Srdivacky */ 1448204643Srdivackyclass StoredDiagnostic { 1449218893Sdim unsigned ID; 1450226633Sdim DiagnosticsEngine::Level Level; 1451204643Srdivacky FullSourceLoc Loc; 1452204643Srdivacky std::string Message; 1453210299Sed std::vector<CharSourceRange> Ranges; 1454206084Srdivacky std::vector<FixItHint> FixIts; 1455204643Srdivacky 1456204643Srdivackypublic: 1457296417Sdim StoredDiagnostic() = default; 1458226633Sdim StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info); 1459341825Sdim StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID, 1460226633Sdim StringRef Message); 1461341825Sdim StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID, 1462226633Sdim StringRef Message, FullSourceLoc Loc, 1463226633Sdim ArrayRef<CharSourceRange> Ranges, 1464226633Sdim ArrayRef<FixItHint> Fixits); 1465204643Srdivacky 1466341825Sdim /// Evaluates true when this object stores a diagnostic. 1467314564Sdim explicit operator bool() const { return !Message.empty(); } 1468204643Srdivacky 1469218893Sdim unsigned getID() const { return ID; } 1470226633Sdim DiagnosticsEngine::Level getLevel() const { return Level; } 1471204643Srdivacky const FullSourceLoc &getLocation() const { return Loc; } 1472226633Sdim StringRef getMessage() const { return Message; } 1473212904Sdim 1474212904Sdim void setLocation(FullSourceLoc Loc) { this->Loc = Loc; } 1475212904Sdim 1476341825Sdim using range_iterator = std::vector<CharSourceRange>::const_iterator; 1477341825Sdim 1478204643Srdivacky range_iterator range_begin() const { return Ranges.begin(); } 1479204643Srdivacky range_iterator range_end() const { return Ranges.end(); } 1480204643Srdivacky unsigned range_size() const { return Ranges.size(); } 1481341825Sdim 1482234353Sdim ArrayRef<CharSourceRange> getRanges() const { 1483234353Sdim return llvm::makeArrayRef(Ranges); 1484234353Sdim } 1485204643Srdivacky 1486341825Sdim using fixit_iterator = std::vector<FixItHint>::const_iterator; 1487341825Sdim 1488204643Srdivacky fixit_iterator fixit_begin() const { return FixIts.begin(); } 1489204643Srdivacky fixit_iterator fixit_end() const { return FixIts.end(); } 1490204643Srdivacky unsigned fixit_size() const { return FixIts.size(); } 1491341825Sdim 1492234353Sdim ArrayRef<FixItHint> getFixIts() const { 1493234353Sdim return llvm::makeArrayRef(FixIts); 1494234353Sdim } 1495193326Sed}; 1496198092Srdivacky 1497341825Sdim/// Abstract interface, implemented by clients of the front-end, which 1498239462Sdim/// formats and prints fully processed diagnostics. 1499226633Sdimclass DiagnosticConsumer { 1500218893Sdimprotected: 1501314564Sdim unsigned NumWarnings = 0; ///< Number of warnings reported 1502314564Sdim unsigned NumErrors = 0; ///< Number of errors reported 1503341825Sdim 1504193326Sedpublic: 1505314564Sdim DiagnosticConsumer() = default; 1506314564Sdim virtual ~DiagnosticConsumer(); 1507314564Sdim 1508218893Sdim unsigned getNumErrors() const { return NumErrors; } 1509218893Sdim unsigned getNumWarnings() const { return NumWarnings; } 1510234353Sdim virtual void clear() { NumWarnings = NumErrors = 0; } 1511218893Sdim 1512341825Sdim /// Callback to inform the diagnostic client that processing 1513198954Srdivacky /// of a source file is beginning. 1514198954Srdivacky /// 1515198954Srdivacky /// Note that diagnostics may be emitted outside the processing of a source 1516198954Srdivacky /// file, for example during the parsing of command line options. However, 1517198954Srdivacky /// diagnostics with source range information are required to only be emitted 1518198954Srdivacky /// in between BeginSourceFile() and EndSourceFile(). 1519198954Srdivacky /// 1520239462Sdim /// \param LangOpts The language options for the source file being processed. 1521341825Sdim /// \param PP The preprocessor object being used for the source; this is 1522239462Sdim /// optional, e.g., it may not be present when processing AST source files. 1523199482Srdivacky virtual void BeginSourceFile(const LangOptions &LangOpts, 1524276479Sdim const Preprocessor *PP = nullptr) {} 1525198092Srdivacky 1526341825Sdim /// Callback to inform the diagnostic client that processing 1527239462Sdim /// of a source file has ended. 1528239462Sdim /// 1529239462Sdim /// The diagnostic client should assume that any objects made available via 1530239462Sdim /// BeginSourceFile() are inaccessible. 1531198954Srdivacky virtual void EndSourceFile() {} 1532198954Srdivacky 1533341825Sdim /// Callback to inform the diagnostic client that processing of all 1534234353Sdim /// source files has ended. 1535234353Sdim virtual void finish() {} 1536234353Sdim 1537341825Sdim /// Indicates whether the diagnostics handled by this 1538226633Sdim /// DiagnosticConsumer should be included in the number of diagnostics 1539226633Sdim /// reported by DiagnosticsEngine. 1540239462Sdim /// 1541239462Sdim /// The default implementation returns true. 1542193326Sed virtual bool IncludeInDiagnosticCounts() const; 1543193326Sed 1544341825Sdim /// Handle this diagnostic, reporting it to the user or 1545193326Sed /// capturing it to a log as needed. 1546218893Sdim /// 1547239462Sdim /// The default implementation just keeps track of the total number of 1548239462Sdim /// warnings and errors. 1549226633Sdim virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 1550226633Sdim const Diagnostic &Info); 1551193326Sed}; 1552193326Sed 1553341825Sdim/// A diagnostic client that ignores all diagnostics. 1554226633Sdimclass IgnoringDiagConsumer : public DiagnosticConsumer { 1555234353Sdim virtual void anchor(); 1556314564Sdim 1557226633Sdim void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 1558276479Sdim const Diagnostic &Info) override { 1559226633Sdim // Just ignore it. 1560226633Sdim } 1561226633Sdim}; 1562226633Sdim 1563341825Sdim/// Diagnostic consumer that forwards diagnostics along to an 1564251662Sdim/// existing, already-initialized diagnostic consumer. 1565251662Sdim/// 1566251662Sdimclass ForwardingDiagnosticConsumer : public DiagnosticConsumer { 1567251662Sdim DiagnosticConsumer &Target; 1568251662Sdim 1569251662Sdimpublic: 1570251662Sdim ForwardingDiagnosticConsumer(DiagnosticConsumer &Target) : Target(Target) {} 1571288943Sdim ~ForwardingDiagnosticConsumer() override; 1572251662Sdim 1573276479Sdim void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 1574276479Sdim const Diagnostic &Info) override; 1575276479Sdim void clear() override; 1576251662Sdim 1577276479Sdim bool IncludeInDiagnosticCounts() const override; 1578251662Sdim}; 1579251662Sdim 1580239462Sdim// Struct used for sending info about how a type should be printed. 1581239462Sdimstruct TemplateDiffTypes { 1582239462Sdim intptr_t FromType; 1583239462Sdim intptr_t ToType; 1584239462Sdim unsigned PrintTree : 1; 1585239462Sdim unsigned PrintFromType : 1; 1586239462Sdim unsigned ElideType : 1; 1587239462Sdim unsigned ShowColors : 1; 1588341825Sdim 1589239462Sdim // The printer sets this variable to true if the template diff was used. 1590239462Sdim unsigned TemplateDiffUsed : 1; 1591239462Sdim}; 1592239462Sdim 1593239462Sdim/// Special character that the diagnostic printer will use to toggle the bold 1594239462Sdim/// attribute. The character itself will be not be printed. 1595239462Sdimconst char ToggleHighlight = 127; 1596239462Sdim 1597276479Sdim/// ProcessWarningOptions - Initialize the diagnostic client and process the 1598276479Sdim/// warning options specified on the command line. 1599276479Sdimvoid ProcessWarningOptions(DiagnosticsEngine &Diags, 1600276479Sdim const DiagnosticOptions &Opts, 1601276479Sdim bool ReportDiags = true); 1602276479Sdim 1603341825Sdim} // namespace clang 1604193326Sed 1605314564Sdim#endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H 1606