1 //===- Diagnostic.h - C Language Family Diagnostic Handling -----*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 /// \file 10 /// Defines the Diagnostic-related interfaces. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_H 15 #define LLVM_CLANG_BASIC_DIAGNOSTIC_H 16 17 #include "clang/Basic/DiagnosticIDs.h" 18 #include "clang/Basic/DiagnosticOptions.h" 19 #include "clang/Basic/SourceLocation.h" 20 #include "clang/Basic/Specifiers.h" 21 #include "llvm/ADT/ArrayRef.h" 22 #include "llvm/ADT/DenseMap.h" 23 #include "llvm/ADT/IntrusiveRefCntPtr.h" 24 #include "llvm/ADT/SmallVector.h" 25 #include "llvm/ADT/StringRef.h" 26 #include "llvm/ADT/iterator_range.h" 27 #include "llvm/Support/Compiler.h" 28 #include "llvm/Support/Error.h" 29 #include <cassert> 30 #include <cstdint> 31 #include <limits> 32 #include <list> 33 #include <map> 34 #include <memory> 35 #include <string> 36 #include <type_traits> 37 #include <utility> 38 #include <vector> 39 40 namespace clang { 41 42 class DeclContext; 43 class DiagnosticBuilder; 44 class DiagnosticConsumer; 45 class IdentifierInfo; 46 class LangOptions; 47 class Preprocessor; 48 class SourceManager; 49 class StoredDiagnostic; 50 51 namespace tok { 52 53 enum TokenKind : unsigned short; 54 55 } // namespace tok 56 57 /// Annotates a diagnostic with some code that should be 58 /// inserted, removed, or replaced to fix the problem. 59 /// 60 /// This kind of hint should be used when we are certain that the 61 /// introduction, removal, or modification of a particular (small!) 62 /// amount of code will correct a compilation error. The compiler 63 /// should also provide full recovery from such errors, such that 64 /// suppressing the diagnostic output can still result in successful 65 /// compilation. 66 class FixItHint { 67 public: 68 /// Code that should be replaced to correct the error. Empty for an 69 /// insertion hint. 70 CharSourceRange RemoveRange; 71 72 /// Code in the specific range that should be inserted in the insertion 73 /// location. 74 CharSourceRange InsertFromRange; 75 76 /// The actual code to insert at the insertion location, as a 77 /// string. 78 std::string CodeToInsert; 79 80 bool BeforePreviousInsertions = false; 81 82 /// Empty code modification hint, indicating that no code 83 /// modification is known. 84 FixItHint() = default; 85 86 bool isNull() const { 87 return !RemoveRange.isValid(); 88 } 89 90 /// Create a code modification hint that inserts the given 91 /// code string at a specific location. 92 static FixItHint CreateInsertion(SourceLocation InsertionLoc, 93 StringRef Code, 94 bool BeforePreviousInsertions = false) { 95 FixItHint Hint; 96 Hint.RemoveRange = 97 CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); 98 Hint.CodeToInsert = Code; 99 Hint.BeforePreviousInsertions = BeforePreviousInsertions; 100 return Hint; 101 } 102 103 /// Create a code modification hint that inserts the given 104 /// code from \p FromRange at a specific location. 105 static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc, 106 CharSourceRange FromRange, 107 bool BeforePreviousInsertions = false) { 108 FixItHint Hint; 109 Hint.RemoveRange = 110 CharSourceRange::getCharRange(InsertionLoc, InsertionLoc); 111 Hint.InsertFromRange = FromRange; 112 Hint.BeforePreviousInsertions = BeforePreviousInsertions; 113 return Hint; 114 } 115 116 /// Create a code modification hint that removes the given 117 /// source range. 118 static FixItHint CreateRemoval(CharSourceRange RemoveRange) { 119 FixItHint Hint; 120 Hint.RemoveRange = RemoveRange; 121 return Hint; 122 } 123 static FixItHint CreateRemoval(SourceRange RemoveRange) { 124 return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange)); 125 } 126 127 /// Create a code modification hint that replaces the given 128 /// source range with the given code string. 129 static FixItHint CreateReplacement(CharSourceRange RemoveRange, 130 StringRef Code) { 131 FixItHint Hint; 132 Hint.RemoveRange = RemoveRange; 133 Hint.CodeToInsert = Code; 134 return Hint; 135 } 136 137 static FixItHint CreateReplacement(SourceRange RemoveRange, 138 StringRef Code) { 139 return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code); 140 } 141 }; 142 143 /// Concrete class used by the front-end to report problems and issues. 144 /// 145 /// This massages the diagnostics (e.g. handling things like "report warnings 146 /// as errors" and passes them off to the DiagnosticConsumer for reporting to 147 /// the user. DiagnosticsEngine is tied to one translation unit and one 148 /// SourceManager. 149 class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { 150 public: 151 /// The level of the diagnostic, after it has been through mapping. 152 enum Level { 153 Ignored = DiagnosticIDs::Ignored, 154 Note = DiagnosticIDs::Note, 155 Remark = DiagnosticIDs::Remark, 156 Warning = DiagnosticIDs::Warning, 157 Error = DiagnosticIDs::Error, 158 Fatal = DiagnosticIDs::Fatal 159 }; 160 161 enum ArgumentKind { 162 /// std::string 163 ak_std_string, 164 165 /// const char * 166 ak_c_string, 167 168 /// int 169 ak_sint, 170 171 /// unsigned 172 ak_uint, 173 174 /// enum TokenKind : unsigned 175 ak_tokenkind, 176 177 /// IdentifierInfo 178 ak_identifierinfo, 179 180 /// address space 181 ak_addrspace, 182 183 /// Qualifiers 184 ak_qual, 185 186 /// QualType 187 ak_qualtype, 188 189 /// DeclarationName 190 ak_declarationname, 191 192 /// NamedDecl * 193 ak_nameddecl, 194 195 /// NestedNameSpecifier * 196 ak_nestednamespec, 197 198 /// DeclContext * 199 ak_declcontext, 200 201 /// pair<QualType, QualType> 202 ak_qualtype_pair, 203 204 /// Attr * 205 ak_attr 206 }; 207 208 /// Represents on argument value, which is a union discriminated 209 /// by ArgumentKind, with a value. 210 using ArgumentValue = std::pair<ArgumentKind, intptr_t>; 211 212 private: 213 // Used by __extension__ 214 unsigned char AllExtensionsSilenced = 0; 215 216 // Treat fatal errors like errors. 217 bool FatalsAsError = false; 218 219 // Suppress all diagnostics. 220 bool SuppressAllDiagnostics = false; 221 222 // Elide common types of templates. 223 bool ElideType = true; 224 225 // Print a tree when comparing templates. 226 bool PrintTemplateTree = false; 227 228 // Color printing is enabled. 229 bool ShowColors = false; 230 231 // Which overload candidates to show. 232 OverloadsShown ShowOverloads = Ovl_All; 233 234 // Cap of # errors emitted, 0 -> no limit. 235 unsigned ErrorLimit = 0; 236 237 // Cap on depth of template backtrace stack, 0 -> no limit. 238 unsigned TemplateBacktraceLimit = 0; 239 240 // Cap on depth of constexpr evaluation backtrace stack, 0 -> no limit. 241 unsigned ConstexprBacktraceLimit = 0; 242 243 IntrusiveRefCntPtr<DiagnosticIDs> Diags; 244 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; 245 DiagnosticConsumer *Client = nullptr; 246 std::unique_ptr<DiagnosticConsumer> Owner; 247 SourceManager *SourceMgr = nullptr; 248 249 /// Mapping information for diagnostics. 250 /// 251 /// Mapping info is packed into four bits per diagnostic. The low three 252 /// bits are the mapping (an instance of diag::Severity), or zero if unset. 253 /// The high bit is set when the mapping was established as a user mapping. 254 /// If the high bit is clear, then the low bits are set to the default 255 /// value, and should be mapped with -pedantic, -Werror, etc. 256 /// 257 /// A new DiagState is created and kept around when diagnostic pragmas modify 258 /// the state so that we know what is the diagnostic state at any given 259 /// source location. 260 class DiagState { 261 llvm::DenseMap<unsigned, DiagnosticMapping> DiagMap; 262 263 public: 264 // "Global" configuration state that can actually vary between modules. 265 266 // Ignore all warnings: -w 267 unsigned IgnoreAllWarnings : 1; 268 269 // Enable all warnings. 270 unsigned EnableAllWarnings : 1; 271 272 // Treat warnings like errors. 273 unsigned WarningsAsErrors : 1; 274 275 // Treat errors like fatal errors. 276 unsigned ErrorsAsFatal : 1; 277 278 // Suppress warnings in system headers. 279 unsigned SuppressSystemWarnings : 1; 280 281 // Map extensions to warnings or errors? 282 diag::Severity ExtBehavior = diag::Severity::Ignored; 283 284 DiagState() 285 : IgnoreAllWarnings(false), EnableAllWarnings(false), 286 WarningsAsErrors(false), ErrorsAsFatal(false), 287 SuppressSystemWarnings(false) {} 288 289 using iterator = llvm::DenseMap<unsigned, DiagnosticMapping>::iterator; 290 using const_iterator = 291 llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator; 292 293 void setMapping(diag::kind Diag, DiagnosticMapping Info) { 294 DiagMap[Diag] = Info; 295 } 296 297 DiagnosticMapping lookupMapping(diag::kind Diag) const { 298 return DiagMap.lookup(Diag); 299 } 300 301 DiagnosticMapping &getOrAddMapping(diag::kind Diag); 302 303 const_iterator begin() const { return DiagMap.begin(); } 304 const_iterator end() const { return DiagMap.end(); } 305 }; 306 307 /// Keeps and automatically disposes all DiagStates that we create. 308 std::list<DiagState> DiagStates; 309 310 /// A mapping from files to the diagnostic states for those files. Lazily 311 /// built on demand for files in which the diagnostic state has not changed. 312 class DiagStateMap { 313 public: 314 /// Add an initial diagnostic state. 315 void appendFirst(DiagState *State); 316 317 /// Add a new latest state point. 318 void append(SourceManager &SrcMgr, SourceLocation Loc, DiagState *State); 319 320 /// Look up the diagnostic state at a given source location. 321 DiagState *lookup(SourceManager &SrcMgr, SourceLocation Loc) const; 322 323 /// Determine whether this map is empty. 324 bool empty() const { return Files.empty(); } 325 326 /// Clear out this map. 327 void clear() { 328 Files.clear(); 329 FirstDiagState = CurDiagState = nullptr; 330 CurDiagStateLoc = SourceLocation(); 331 } 332 333 /// Produce a debugging dump of the diagnostic state. 334 LLVM_DUMP_METHOD void dump(SourceManager &SrcMgr, 335 StringRef DiagName = StringRef()) const; 336 337 /// Grab the most-recently-added state point. 338 DiagState *getCurDiagState() const { return CurDiagState; } 339 340 /// Get the location at which a diagnostic state was last added. 341 SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; } 342 343 private: 344 friend class ASTReader; 345 friend class ASTWriter; 346 347 /// Represents a point in source where the diagnostic state was 348 /// modified because of a pragma. 349 /// 350 /// 'Loc' can be null if the point represents the diagnostic state 351 /// modifications done through the command-line. 352 struct DiagStatePoint { 353 DiagState *State; 354 unsigned Offset; 355 356 DiagStatePoint(DiagState *State, unsigned Offset) 357 : State(State), Offset(Offset) {} 358 }; 359 360 /// Description of the diagnostic states and state transitions for a 361 /// particular FileID. 362 struct File { 363 /// The diagnostic state for the parent file. This is strictly redundant, 364 /// as looking up the DecomposedIncludedLoc for the FileID in the Files 365 /// map would give us this, but we cache it here for performance. 366 File *Parent = nullptr; 367 368 /// The offset of this file within its parent. 369 unsigned ParentOffset = 0; 370 371 /// Whether this file has any local (not imported from an AST file) 372 /// diagnostic state transitions. 373 bool HasLocalTransitions = false; 374 375 /// The points within the file where the state changes. There will always 376 /// be at least one of these (the state on entry to the file). 377 llvm::SmallVector<DiagStatePoint, 4> StateTransitions; 378 379 DiagState *lookup(unsigned Offset) const; 380 }; 381 382 /// The diagnostic states for each file. 383 mutable std::map<FileID, File> Files; 384 385 /// The initial diagnostic state. 386 DiagState *FirstDiagState; 387 388 /// The current diagnostic state. 389 DiagState *CurDiagState; 390 391 /// The location at which the current diagnostic state was established. 392 SourceLocation CurDiagStateLoc; 393 394 /// Get the diagnostic state information for a file. 395 File *getFile(SourceManager &SrcMgr, FileID ID) const; 396 }; 397 398 DiagStateMap DiagStatesByLoc; 399 400 /// Keeps the DiagState that was active during each diagnostic 'push' 401 /// so we can get back at it when we 'pop'. 402 std::vector<DiagState *> DiagStateOnPushStack; 403 404 DiagState *GetCurDiagState() const { 405 return DiagStatesByLoc.getCurDiagState(); 406 } 407 408 void PushDiagStatePoint(DiagState *State, SourceLocation L); 409 410 /// Finds the DiagStatePoint that contains the diagnostic state of 411 /// the given source location. 412 DiagState *GetDiagStateForLoc(SourceLocation Loc) const { 413 return SourceMgr ? DiagStatesByLoc.lookup(*SourceMgr, Loc) 414 : DiagStatesByLoc.getCurDiagState(); 415 } 416 417 /// Sticky flag set to \c true when an error is emitted. 418 bool ErrorOccurred; 419 420 /// Sticky flag set to \c true when an "uncompilable error" occurs. 421 /// I.e. an error that was not upgraded from a warning by -Werror. 422 bool UncompilableErrorOccurred; 423 424 /// Sticky flag set to \c true when a fatal error is emitted. 425 bool FatalErrorOccurred; 426 427 /// Indicates that an unrecoverable error has occurred. 428 bool UnrecoverableErrorOccurred; 429 430 /// Counts for DiagnosticErrorTrap to check whether an error occurred 431 /// during a parsing section, e.g. during parsing a function. 432 unsigned TrapNumErrorsOccurred; 433 unsigned TrapNumUnrecoverableErrorsOccurred; 434 435 /// The level of the last diagnostic emitted. 436 /// 437 /// This is used to emit continuation diagnostics with the same level as the 438 /// diagnostic that they follow. 439 DiagnosticIDs::Level LastDiagLevel; 440 441 /// Number of warnings reported 442 unsigned NumWarnings; 443 444 /// Number of errors reported 445 unsigned NumErrors; 446 447 /// A function pointer that converts an opaque diagnostic 448 /// argument to a strings. 449 /// 450 /// This takes the modifiers and argument that was present in the diagnostic. 451 /// 452 /// The PrevArgs array indicates the previous arguments formatted for this 453 /// diagnostic. Implementations of this function can use this information to 454 /// avoid redundancy across arguments. 455 /// 456 /// This is a hack to avoid a layering violation between libbasic and libsema. 457 using ArgToStringFnTy = void (*)( 458 ArgumentKind Kind, intptr_t Val, 459 StringRef Modifier, StringRef Argument, 460 ArrayRef<ArgumentValue> PrevArgs, 461 SmallVectorImpl<char> &Output, 462 void *Cookie, 463 ArrayRef<intptr_t> QualTypeVals); 464 465 void *ArgToStringCookie = nullptr; 466 ArgToStringFnTy ArgToStringFn; 467 468 /// ID of the "delayed" diagnostic, which is a (typically 469 /// fatal) diagnostic that had to be delayed because it was found 470 /// while emitting another diagnostic. 471 unsigned DelayedDiagID; 472 473 /// First string argument for the delayed diagnostic. 474 std::string DelayedDiagArg1; 475 476 /// Second string argument for the delayed diagnostic. 477 std::string DelayedDiagArg2; 478 479 /// Third string argument for the delayed diagnostic. 480 std::string DelayedDiagArg3; 481 482 /// Optional flag value. 483 /// 484 /// Some flags accept values, for instance: -Wframe-larger-than=<value> and 485 /// -Rpass=<value>. The content of this string is emitted after the flag name 486 /// and '='. 487 std::string FlagValue; 488 489 public: 490 explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags, 491 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, 492 DiagnosticConsumer *client = nullptr, 493 bool ShouldOwnClient = true); 494 DiagnosticsEngine(const DiagnosticsEngine &) = delete; 495 DiagnosticsEngine &operator=(const DiagnosticsEngine &) = delete; 496 ~DiagnosticsEngine(); 497 498 LLVM_DUMP_METHOD void dump() const; 499 LLVM_DUMP_METHOD void dump(StringRef DiagName) const; 500 501 const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const { 502 return Diags; 503 } 504 505 /// Retrieve the diagnostic options. 506 DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; } 507 508 using diag_mapping_range = llvm::iterator_range<DiagState::const_iterator>; 509 510 /// Get the current set of diagnostic mappings. 511 diag_mapping_range getDiagnosticMappings() const { 512 const DiagState &DS = *GetCurDiagState(); 513 return diag_mapping_range(DS.begin(), DS.end()); 514 } 515 516 DiagnosticConsumer *getClient() { return Client; } 517 const DiagnosticConsumer *getClient() const { return Client; } 518 519 /// Determine whether this \c DiagnosticsEngine object own its client. 520 bool ownsClient() const { return Owner != nullptr; } 521 522 /// Return the current diagnostic client along with ownership of that 523 /// client. 524 std::unique_ptr<DiagnosticConsumer> takeClient() { return std::move(Owner); } 525 526 bool hasSourceManager() const { return SourceMgr != nullptr; } 527 528 SourceManager &getSourceManager() const { 529 assert(SourceMgr && "SourceManager not set!"); 530 return *SourceMgr; 531 } 532 533 void setSourceManager(SourceManager *SrcMgr) { 534 assert(DiagStatesByLoc.empty() && 535 "Leftover diag state from a different SourceManager."); 536 SourceMgr = SrcMgr; 537 } 538 539 //===--------------------------------------------------------------------===// 540 // DiagnosticsEngine characterization methods, used by a client to customize 541 // how diagnostics are emitted. 542 // 543 544 /// Copies the current DiagMappings and pushes the new copy 545 /// onto the top of the stack. 546 void pushMappings(SourceLocation Loc); 547 548 /// Pops the current DiagMappings off the top of the stack, 549 /// causing the new top of the stack to be the active mappings. 550 /// 551 /// \returns \c true if the pop happens, \c false if there is only one 552 /// DiagMapping on the stack. 553 bool popMappings(SourceLocation Loc); 554 555 /// Set the diagnostic client associated with this diagnostic object. 556 /// 557 /// \param ShouldOwnClient true if the diagnostic object should take 558 /// ownership of \c client. 559 void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true); 560 561 /// Specify a limit for the number of errors we should 562 /// emit before giving up. 563 /// 564 /// Zero disables the limit. 565 void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; } 566 567 /// Specify the maximum number of template instantiation 568 /// notes to emit along with a given diagnostic. 569 void setTemplateBacktraceLimit(unsigned Limit) { 570 TemplateBacktraceLimit = Limit; 571 } 572 573 /// Retrieve the maximum number of template instantiation 574 /// notes to emit along with a given diagnostic. 575 unsigned getTemplateBacktraceLimit() const { 576 return TemplateBacktraceLimit; 577 } 578 579 /// Specify the maximum number of constexpr evaluation 580 /// notes to emit along with a given diagnostic. 581 void setConstexprBacktraceLimit(unsigned Limit) { 582 ConstexprBacktraceLimit = Limit; 583 } 584 585 /// Retrieve the maximum number of constexpr evaluation 586 /// notes to emit along with a given diagnostic. 587 unsigned getConstexprBacktraceLimit() const { 588 return ConstexprBacktraceLimit; 589 } 590 591 /// When set to true, any unmapped warnings are ignored. 592 /// 593 /// If this and WarningsAsErrors are both set, then this one wins. 594 void setIgnoreAllWarnings(bool Val) { 595 GetCurDiagState()->IgnoreAllWarnings = Val; 596 } 597 bool getIgnoreAllWarnings() const { 598 return GetCurDiagState()->IgnoreAllWarnings; 599 } 600 601 /// When set to true, any unmapped ignored warnings are no longer 602 /// ignored. 603 /// 604 /// If this and IgnoreAllWarnings are both set, then that one wins. 605 void setEnableAllWarnings(bool Val) { 606 GetCurDiagState()->EnableAllWarnings = Val; 607 } 608 bool getEnableAllWarnings() const { 609 return GetCurDiagState()->EnableAllWarnings; 610 } 611 612 /// When set to true, any warnings reported are issued as errors. 613 void setWarningsAsErrors(bool Val) { 614 GetCurDiagState()->WarningsAsErrors = Val; 615 } 616 bool getWarningsAsErrors() const { 617 return GetCurDiagState()->WarningsAsErrors; 618 } 619 620 /// When set to true, any error reported is made a fatal error. 621 void setErrorsAsFatal(bool Val) { GetCurDiagState()->ErrorsAsFatal = Val; } 622 bool getErrorsAsFatal() const { return GetCurDiagState()->ErrorsAsFatal; } 623 624 /// \brief When set to true, any fatal error reported is made an error. 625 /// 626 /// This setting takes precedence over the setErrorsAsFatal setting above. 627 void setFatalsAsError(bool Val) { FatalsAsError = Val; } 628 bool getFatalsAsError() const { return FatalsAsError; } 629 630 /// When set to true mask warnings that come from system headers. 631 void setSuppressSystemWarnings(bool Val) { 632 GetCurDiagState()->SuppressSystemWarnings = Val; 633 } 634 bool getSuppressSystemWarnings() const { 635 return GetCurDiagState()->SuppressSystemWarnings; 636 } 637 638 /// Suppress all diagnostics, to silence the front end when we 639 /// know that we don't want any more diagnostics to be passed along to the 640 /// client 641 void setSuppressAllDiagnostics(bool Val) { SuppressAllDiagnostics = Val; } 642 bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; } 643 644 /// Set type eliding, to skip outputting same types occurring in 645 /// template types. 646 void setElideType(bool Val) { ElideType = Val; } 647 bool getElideType() { return ElideType; } 648 649 /// Set tree printing, to outputting the template difference in a 650 /// tree format. 651 void setPrintTemplateTree(bool Val) { PrintTemplateTree = Val; } 652 bool getPrintTemplateTree() { return PrintTemplateTree; } 653 654 /// Set color printing, so the type diffing will inject color markers 655 /// into the output. 656 void setShowColors(bool Val) { ShowColors = Val; } 657 bool getShowColors() { return ShowColors; } 658 659 /// Specify which overload candidates to show when overload resolution 660 /// fails. 661 /// 662 /// By default, we show all candidates. 663 void setShowOverloads(OverloadsShown Val) { 664 ShowOverloads = Val; 665 } 666 OverloadsShown getShowOverloads() const { return ShowOverloads; } 667 668 /// Pretend that the last diagnostic issued was ignored, so any 669 /// subsequent notes will be suppressed, or restore a prior ignoring 670 /// state after ignoring some diagnostics and their notes, possibly in 671 /// the middle of another diagnostic. 672 /// 673 /// This can be used by clients who suppress diagnostics themselves. 674 void setLastDiagnosticIgnored(bool Ignored) { 675 if (LastDiagLevel == DiagnosticIDs::Fatal) 676 FatalErrorOccurred = true; 677 LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning; 678 } 679 680 /// Determine whether the previous diagnostic was ignored. This can 681 /// be used by clients that want to determine whether notes attached to a 682 /// diagnostic will be suppressed. 683 bool isLastDiagnosticIgnored() const { 684 return LastDiagLevel == DiagnosticIDs::Ignored; 685 } 686 687 /// Controls whether otherwise-unmapped extension diagnostics are 688 /// mapped onto ignore/warning/error. 689 /// 690 /// This corresponds to the GCC -pedantic and -pedantic-errors option. 691 void setExtensionHandlingBehavior(diag::Severity H) { 692 GetCurDiagState()->ExtBehavior = H; 693 } 694 diag::Severity getExtensionHandlingBehavior() const { 695 return GetCurDiagState()->ExtBehavior; 696 } 697 698 /// Counter bumped when an __extension__ block is/ encountered. 699 /// 700 /// When non-zero, all extension diagnostics are entirely silenced, no 701 /// matter how they are mapped. 702 void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; } 703 void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; } 704 bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; } 705 706 /// This allows the client to specify that certain warnings are 707 /// ignored. 708 /// 709 /// Notes can never be mapped, errors can only be mapped to fatal, and 710 /// WARNINGs and EXTENSIONs can be mapped arbitrarily. 711 /// 712 /// \param Loc The source location that this change of diagnostic state should 713 /// take affect. It can be null if we are setting the latest state. 714 void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc); 715 716 /// Change an entire diagnostic group (e.g. "unknown-pragmas") to 717 /// have the specified mapping. 718 /// 719 /// \returns true (and ignores the request) if "Group" was unknown, false 720 /// otherwise. 721 /// 722 /// \param Flavor The flavor of group to affect. -Rfoo does not affect the 723 /// state of the -Wfoo group and vice versa. 724 /// 725 /// \param Loc The source location that this change of diagnostic state should 726 /// take affect. It can be null if we are setting the state from command-line. 727 bool setSeverityForGroup(diag::Flavor Flavor, StringRef Group, 728 diag::Severity Map, 729 SourceLocation Loc = SourceLocation()); 730 731 /// Set the warning-as-error flag for the given diagnostic group. 732 /// 733 /// This function always only operates on the current diagnostic state. 734 /// 735 /// \returns True if the given group is unknown, false otherwise. 736 bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled); 737 738 /// Set the error-as-fatal flag for the given diagnostic group. 739 /// 740 /// This function always only operates on the current diagnostic state. 741 /// 742 /// \returns True if the given group is unknown, false otherwise. 743 bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled); 744 745 /// Add the specified mapping to all diagnostics of the specified 746 /// flavor. 747 /// 748 /// Mainly to be used by -Wno-everything to disable all warnings but allow 749 /// subsequent -W options to enable specific warnings. 750 void setSeverityForAll(diag::Flavor Flavor, diag::Severity Map, 751 SourceLocation Loc = SourceLocation()); 752 753 bool hasErrorOccurred() const { return ErrorOccurred; } 754 755 /// Errors that actually prevent compilation, not those that are 756 /// upgraded from a warning by -Werror. 757 bool hasUncompilableErrorOccurred() const { 758 return UncompilableErrorOccurred; 759 } 760 bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } 761 762 /// Determine whether any kind of unrecoverable error has occurred. 763 bool hasUnrecoverableErrorOccurred() const { 764 return FatalErrorOccurred || UnrecoverableErrorOccurred; 765 } 766 767 unsigned getNumWarnings() const { return NumWarnings; } 768 769 void setNumWarnings(unsigned NumWarnings) { 770 this->NumWarnings = NumWarnings; 771 } 772 773 /// Return an ID for a diagnostic with the specified format string and 774 /// level. 775 /// 776 /// If this is the first request for this diagnostic, it is registered and 777 /// created, otherwise the existing ID is returned. 778 /// 779 /// \param FormatString A fixed diagnostic format string that will be hashed 780 /// and mapped to a unique DiagID. 781 template <unsigned N> 782 unsigned getCustomDiagID(Level L, const char (&FormatString)[N]) { 783 return Diags->getCustomDiagID((DiagnosticIDs::Level)L, 784 StringRef(FormatString, N - 1)); 785 } 786 787 /// Converts a diagnostic argument (as an intptr_t) into the string 788 /// that represents it. 789 void ConvertArgToString(ArgumentKind Kind, intptr_t Val, 790 StringRef Modifier, StringRef Argument, 791 ArrayRef<ArgumentValue> PrevArgs, 792 SmallVectorImpl<char> &Output, 793 ArrayRef<intptr_t> QualTypeVals) const { 794 ArgToStringFn(Kind, Val, Modifier, Argument, PrevArgs, Output, 795 ArgToStringCookie, QualTypeVals); 796 } 797 798 void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { 799 ArgToStringFn = Fn; 800 ArgToStringCookie = Cookie; 801 } 802 803 /// Note that the prior diagnostic was emitted by some other 804 /// \c DiagnosticsEngine, and we may be attaching a note to that diagnostic. 805 void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) { 806 LastDiagLevel = Other.LastDiagLevel; 807 } 808 809 /// Reset the state of the diagnostic object to its initial 810 /// configuration. 811 void Reset(); 812 813 //===--------------------------------------------------------------------===// 814 // DiagnosticsEngine classification and reporting interfaces. 815 // 816 817 /// Determine whether the diagnostic is known to be ignored. 818 /// 819 /// This can be used to opportunistically avoid expensive checks when it's 820 /// known for certain that the diagnostic has been suppressed at the 821 /// specified location \p Loc. 822 /// 823 /// \param Loc The source location we are interested in finding out the 824 /// diagnostic state. Can be null in order to query the latest state. 825 bool isIgnored(unsigned DiagID, SourceLocation Loc) const { 826 return Diags->getDiagnosticSeverity(DiagID, Loc, *this) == 827 diag::Severity::Ignored; 828 } 829 830 /// Based on the way the client configured the DiagnosticsEngine 831 /// object, classify the specified diagnostic ID into a Level, consumable by 832 /// the DiagnosticConsumer. 833 /// 834 /// To preserve invariant assumptions, this function should not be used to 835 /// influence parse or semantic analysis actions. Instead consider using 836 /// \c isIgnored(). 837 /// 838 /// \param Loc The source location we are interested in finding out the 839 /// diagnostic state. Can be null in order to query the latest state. 840 Level getDiagnosticLevel(unsigned DiagID, SourceLocation Loc) const { 841 return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this); 842 } 843 844 /// Issue the message to the client. 845 /// 846 /// This actually returns an instance of DiagnosticBuilder which emits the 847 /// diagnostics (through @c ProcessDiag) when it is destroyed. 848 /// 849 /// \param DiagID A member of the @c diag::kind enum. 850 /// \param Loc Represents the source location associated with the diagnostic, 851 /// which can be an invalid location if no position information is available. 852 inline DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID); 853 inline DiagnosticBuilder Report(unsigned DiagID); 854 855 void Report(const StoredDiagnostic &storedDiag); 856 857 /// Determine whethere there is already a diagnostic in flight. 858 bool isDiagnosticInFlight() const { 859 return CurDiagID != std::numeric_limits<unsigned>::max(); 860 } 861 862 /// Set the "delayed" diagnostic that will be emitted once 863 /// the current diagnostic completes. 864 /// 865 /// If a diagnostic is already in-flight but the front end must 866 /// report a problem (e.g., with an inconsistent file system 867 /// state), this routine sets a "delayed" diagnostic that will be 868 /// emitted after the current diagnostic completes. This should 869 /// only be used for fatal errors detected at inconvenient 870 /// times. If emitting a delayed diagnostic causes a second delayed 871 /// diagnostic to be introduced, that second delayed diagnostic 872 /// will be ignored. 873 /// 874 /// \param DiagID The ID of the diagnostic being delayed. 875 /// 876 /// \param Arg1 A string argument that will be provided to the 877 /// diagnostic. A copy of this string will be stored in the 878 /// DiagnosticsEngine object itself. 879 /// 880 /// \param Arg2 A string argument that will be provided to the 881 /// diagnostic. A copy of this string will be stored in the 882 /// DiagnosticsEngine object itself. 883 /// 884 /// \param Arg3 A string argument that will be provided to the 885 /// diagnostic. A copy of this string will be stored in the 886 /// DiagnosticsEngine object itself. 887 void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "", 888 StringRef Arg2 = "", StringRef Arg3 = ""); 889 890 /// Clear out the current diagnostic. 891 void Clear() { CurDiagID = std::numeric_limits<unsigned>::max(); } 892 893 /// Return the value associated with this diagnostic flag. 894 StringRef getFlagValue() const { return FlagValue; } 895 896 private: 897 // This is private state used by DiagnosticBuilder. We put it here instead of 898 // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight 899 // object. This implementation choice means that we can only have one 900 // diagnostic "in flight" at a time, but this seems to be a reasonable 901 // tradeoff to keep these objects small. Assertions verify that only one 902 // diagnostic is in flight at a time. 903 friend class Diagnostic; 904 friend class DiagnosticBuilder; 905 friend class DiagnosticErrorTrap; 906 friend class DiagnosticIDs; 907 friend class PartialDiagnostic; 908 909 /// Report the delayed diagnostic. 910 void ReportDelayed(); 911 912 /// The location of the current diagnostic that is in flight. 913 SourceLocation CurDiagLoc; 914 915 /// The ID of the current diagnostic that is in flight. 916 /// 917 /// This is set to std::numeric_limits<unsigned>::max() when there is no 918 /// diagnostic in flight. 919 unsigned CurDiagID; 920 921 enum { 922 /// The maximum number of arguments we can hold. 923 /// 924 /// We currently only support up to 10 arguments (%0-%9). A single 925 /// diagnostic with more than that almost certainly has to be simplified 926 /// anyway. 927 MaxArguments = 10, 928 }; 929 930 /// The number of entries in Arguments. 931 signed char NumDiagArgs; 932 933 /// Specifies whether an argument is in DiagArgumentsStr or 934 /// in DiagArguments. 935 /// 936 /// This is an array of ArgumentKind::ArgumentKind enum values, one for each 937 /// argument. 938 unsigned char DiagArgumentsKind[MaxArguments]; 939 940 /// Holds the values of each string argument for the current 941 /// diagnostic. 942 /// 943 /// This is only used when the corresponding ArgumentKind is ak_std_string. 944 std::string DiagArgumentsStr[MaxArguments]; 945 946 /// The values for the various substitution positions. 947 /// 948 /// This is used when the argument is not an std::string. The specific 949 /// value is mangled into an intptr_t and the interpretation depends on 950 /// exactly what sort of argument kind it is. 951 intptr_t DiagArgumentsVal[MaxArguments]; 952 953 /// The list of ranges added to this diagnostic. 954 SmallVector<CharSourceRange, 8> DiagRanges; 955 956 /// If valid, provides a hint with some code to insert, remove, 957 /// or modify at a particular position. 958 SmallVector<FixItHint, 8> DiagFixItHints; 959 960 DiagnosticMapping makeUserMapping(diag::Severity Map, SourceLocation L) { 961 bool isPragma = L.isValid(); 962 DiagnosticMapping Mapping = 963 DiagnosticMapping::Make(Map, /*IsUser=*/true, isPragma); 964 965 // If this is a pragma mapping, then set the diagnostic mapping flags so 966 // that we override command line options. 967 if (isPragma) { 968 Mapping.setNoWarningAsError(true); 969 Mapping.setNoErrorAsFatal(true); 970 } 971 972 return Mapping; 973 } 974 975 /// Used to report a diagnostic that is finally fully formed. 976 /// 977 /// \returns true if the diagnostic was emitted, false if it was suppressed. 978 bool ProcessDiag() { 979 return Diags->ProcessDiag(*this); 980 } 981 982 /// @name Diagnostic Emission 983 /// @{ 984 protected: 985 friend class ASTReader; 986 friend class ASTWriter; 987 988 // Sema requires access to the following functions because the current design 989 // of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to 990 // access us directly to ensure we minimize the emitted code for the common 991 // Sema::Diag() patterns. 992 friend class Sema; 993 994 /// Emit the current diagnostic and clear the diagnostic state. 995 /// 996 /// \param Force Emit the diagnostic regardless of suppression settings. 997 bool EmitCurrentDiagnostic(bool Force = false); 998 999 unsigned getCurrentDiagID() const { return CurDiagID; } 1000 1001 SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; } 1002 1003 /// @} 1004 }; 1005 1006 /// RAII class that determines when any errors have occurred 1007 /// between the time the instance was created and the time it was 1008 /// queried. 1009 class DiagnosticErrorTrap { 1010 DiagnosticsEngine &Diag; 1011 unsigned NumErrors; 1012 unsigned NumUnrecoverableErrors; 1013 1014 public: 1015 explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag) 1016 : Diag(Diag) { reset(); } 1017 1018 /// Determine whether any errors have occurred since this 1019 /// object instance was created. 1020 bool hasErrorOccurred() const { 1021 return Diag.TrapNumErrorsOccurred > NumErrors; 1022 } 1023 1024 /// Determine whether any unrecoverable errors have occurred since this 1025 /// object instance was created. 1026 bool hasUnrecoverableErrorOccurred() const { 1027 return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors; 1028 } 1029 1030 /// Set to initial state of "no errors occurred". 1031 void reset() { 1032 NumErrors = Diag.TrapNumErrorsOccurred; 1033 NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred; 1034 } 1035 }; 1036 1037 //===----------------------------------------------------------------------===// 1038 // DiagnosticBuilder 1039 //===----------------------------------------------------------------------===// 1040 1041 /// A little helper class used to produce diagnostics. 1042 /// 1043 /// This is constructed by the DiagnosticsEngine::Report method, and 1044 /// allows insertion of extra information (arguments and source ranges) into 1045 /// the currently "in flight" diagnostic. When the temporary for the builder 1046 /// is destroyed, the diagnostic is issued. 1047 /// 1048 /// Note that many of these will be created as temporary objects (many call 1049 /// sites), so we want them to be small and we never want their address taken. 1050 /// This ensures that compilers with somewhat reasonable optimizers will promote 1051 /// the common fields to registers, eliminating increments of the NumArgs field, 1052 /// for example. 1053 class DiagnosticBuilder { 1054 friend class DiagnosticsEngine; 1055 friend class PartialDiagnostic; 1056 1057 mutable DiagnosticsEngine *DiagObj = nullptr; 1058 mutable unsigned NumArgs = 0; 1059 1060 /// Status variable indicating if this diagnostic is still active. 1061 /// 1062 // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)), 1063 // but LLVM is not currently smart enough to eliminate the null check that 1064 // Emit() would end up with if we used that as our status variable. 1065 mutable bool IsActive = false; 1066 1067 /// Flag indicating that this diagnostic is being emitted via a 1068 /// call to ForceEmit. 1069 mutable bool IsForceEmit = false; 1070 1071 DiagnosticBuilder() = default; 1072 1073 explicit DiagnosticBuilder(DiagnosticsEngine *diagObj) 1074 : DiagObj(diagObj), IsActive(true) { 1075 assert(diagObj && "DiagnosticBuilder requires a valid DiagnosticsEngine!"); 1076 diagObj->DiagRanges.clear(); 1077 diagObj->DiagFixItHints.clear(); 1078 } 1079 1080 protected: 1081 void FlushCounts() { 1082 DiagObj->NumDiagArgs = NumArgs; 1083 } 1084 1085 /// Clear out the current diagnostic. 1086 void Clear() const { 1087 DiagObj = nullptr; 1088 IsActive = false; 1089 IsForceEmit = false; 1090 } 1091 1092 /// Determine whether this diagnostic is still active. 1093 bool isActive() const { return IsActive; } 1094 1095 /// Force the diagnostic builder to emit the diagnostic now. 1096 /// 1097 /// Once this function has been called, the DiagnosticBuilder object 1098 /// should not be used again before it is destroyed. 1099 /// 1100 /// \returns true if a diagnostic was emitted, false if the 1101 /// diagnostic was suppressed. 1102 bool Emit() { 1103 // If this diagnostic is inactive, then its soul was stolen by the copy ctor 1104 // (or by a subclass, as in SemaDiagnosticBuilder). 1105 if (!isActive()) return false; 1106 1107 // When emitting diagnostics, we set the final argument count into 1108 // the DiagnosticsEngine object. 1109 FlushCounts(); 1110 1111 // Process the diagnostic. 1112 bool Result = DiagObj->EmitCurrentDiagnostic(IsForceEmit); 1113 1114 // This diagnostic is dead. 1115 Clear(); 1116 1117 return Result; 1118 } 1119 1120 public: 1121 /// Copy constructor. When copied, this "takes" the diagnostic info from the 1122 /// input and neuters it. 1123 DiagnosticBuilder(const DiagnosticBuilder &D) { 1124 DiagObj = D.DiagObj; 1125 IsActive = D.IsActive; 1126 IsForceEmit = D.IsForceEmit; 1127 D.Clear(); 1128 NumArgs = D.NumArgs; 1129 } 1130 1131 DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete; 1132 1133 /// Emits the diagnostic. 1134 ~DiagnosticBuilder() { 1135 Emit(); 1136 } 1137 1138 /// Forces the diagnostic to be emitted. 1139 const DiagnosticBuilder &setForceEmit() const { 1140 IsForceEmit = true; 1141 return *this; 1142 } 1143 1144 /// Conversion of DiagnosticBuilder to bool always returns \c true. 1145 /// 1146 /// This allows is to be used in boolean error contexts (where \c true is 1147 /// used to indicate that an error has occurred), like: 1148 /// \code 1149 /// return Diag(...); 1150 /// \endcode 1151 operator bool() const { return true; } 1152 1153 void AddString(StringRef S) const { 1154 assert(isActive() && "Clients must not add to cleared diagnostic!"); 1155 assert(NumArgs < DiagnosticsEngine::MaxArguments && 1156 "Too many arguments to diagnostic!"); 1157 DiagObj->DiagArgumentsKind[NumArgs] = DiagnosticsEngine::ak_std_string; 1158 DiagObj->DiagArgumentsStr[NumArgs++] = S; 1159 } 1160 1161 void AddTaggedVal(intptr_t V, DiagnosticsEngine::ArgumentKind Kind) const { 1162 assert(isActive() && "Clients must not add to cleared diagnostic!"); 1163 assert(NumArgs < DiagnosticsEngine::MaxArguments && 1164 "Too many arguments to diagnostic!"); 1165 DiagObj->DiagArgumentsKind[NumArgs] = Kind; 1166 DiagObj->DiagArgumentsVal[NumArgs++] = V; 1167 } 1168 1169 void AddSourceRange(const CharSourceRange &R) const { 1170 assert(isActive() && "Clients must not add to cleared diagnostic!"); 1171 DiagObj->DiagRanges.push_back(R); 1172 } 1173 1174 void AddFixItHint(const FixItHint &Hint) const { 1175 assert(isActive() && "Clients must not add to cleared diagnostic!"); 1176 if (!Hint.isNull()) 1177 DiagObj->DiagFixItHints.push_back(Hint); 1178 } 1179 1180 void addFlagValue(StringRef V) const { DiagObj->FlagValue = V; } 1181 }; 1182 1183 struct AddFlagValue { 1184 StringRef Val; 1185 1186 explicit AddFlagValue(StringRef V) : Val(V) {} 1187 }; 1188 1189 /// Register a value for the flag in the current diagnostic. This 1190 /// value will be shown as the suffix "=value" after the flag name. It is 1191 /// useful in cases where the diagnostic flag accepts values (e.g., 1192 /// -Rpass or -Wframe-larger-than). 1193 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1194 const AddFlagValue V) { 1195 DB.addFlagValue(V.Val); 1196 return DB; 1197 } 1198 1199 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1200 StringRef S) { 1201 DB.AddString(S); 1202 return DB; 1203 } 1204 1205 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1206 const char *Str) { 1207 DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str), 1208 DiagnosticsEngine::ak_c_string); 1209 return DB; 1210 } 1211 1212 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) { 1213 DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); 1214 return DB; 1215 } 1216 1217 // We use enable_if here to prevent that this overload is selected for 1218 // pointers or other arguments that are implicitly convertible to bool. 1219 template <typename T> 1220 inline 1221 typename std::enable_if<std::is_same<T, bool>::value, 1222 const DiagnosticBuilder &>::type 1223 operator<<(const DiagnosticBuilder &DB, T I) { 1224 DB.AddTaggedVal(I, DiagnosticsEngine::ak_sint); 1225 return DB; 1226 } 1227 1228 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1229 unsigned I) { 1230 DB.AddTaggedVal(I, DiagnosticsEngine::ak_uint); 1231 return DB; 1232 } 1233 1234 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1235 tok::TokenKind I) { 1236 DB.AddTaggedVal(static_cast<unsigned>(I), DiagnosticsEngine::ak_tokenkind); 1237 return DB; 1238 } 1239 1240 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1241 const IdentifierInfo *II) { 1242 DB.AddTaggedVal(reinterpret_cast<intptr_t>(II), 1243 DiagnosticsEngine::ak_identifierinfo); 1244 return DB; 1245 } 1246 1247 // Adds a DeclContext to the diagnostic. The enable_if template magic is here 1248 // so that we only match those arguments that are (statically) DeclContexts; 1249 // other arguments that derive from DeclContext (e.g., RecordDecls) will not 1250 // match. 1251 template <typename T> 1252 inline typename std::enable_if< 1253 std::is_same<typename std::remove_const<T>::type, DeclContext>::value, 1254 const DiagnosticBuilder &>::type 1255 operator<<(const DiagnosticBuilder &DB, T *DC) { 1256 DB.AddTaggedVal(reinterpret_cast<intptr_t>(DC), 1257 DiagnosticsEngine::ak_declcontext); 1258 return DB; 1259 } 1260 1261 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1262 SourceRange R) { 1263 DB.AddSourceRange(CharSourceRange::getTokenRange(R)); 1264 return DB; 1265 } 1266 1267 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1268 ArrayRef<SourceRange> Ranges) { 1269 for (SourceRange R : Ranges) 1270 DB.AddSourceRange(CharSourceRange::getTokenRange(R)); 1271 return DB; 1272 } 1273 1274 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1275 const CharSourceRange &R) { 1276 DB.AddSourceRange(R); 1277 return DB; 1278 } 1279 1280 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1281 const FixItHint &Hint) { 1282 DB.AddFixItHint(Hint); 1283 return DB; 1284 } 1285 1286 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1287 ArrayRef<FixItHint> Hints) { 1288 for (const FixItHint &Hint : Hints) 1289 DB.AddFixItHint(Hint); 1290 return DB; 1291 } 1292 1293 /// A nullability kind paired with a bit indicating whether it used a 1294 /// context-sensitive keyword. 1295 using DiagNullabilityKind = std::pair<NullabilityKind, bool>; 1296 1297 const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1298 DiagNullabilityKind nullability); 1299 1300 inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc, 1301 unsigned DiagID) { 1302 assert(CurDiagID == std::numeric_limits<unsigned>::max() && 1303 "Multiple diagnostics in flight at once!"); 1304 CurDiagLoc = Loc; 1305 CurDiagID = DiagID; 1306 FlagValue.clear(); 1307 return DiagnosticBuilder(this); 1308 } 1309 1310 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 1311 llvm::Error &&E) { 1312 DB.AddString(toString(std::move(E))); 1313 return DB; 1314 } 1315 1316 inline DiagnosticBuilder DiagnosticsEngine::Report(unsigned DiagID) { 1317 return Report(SourceLocation(), DiagID); 1318 } 1319 1320 //===----------------------------------------------------------------------===// 1321 // Diagnostic 1322 //===----------------------------------------------------------------------===// 1323 1324 /// A little helper class (which is basically a smart pointer that forwards 1325 /// info from DiagnosticsEngine) that allows clients to enquire about the 1326 /// currently in-flight diagnostic. 1327 class Diagnostic { 1328 const DiagnosticsEngine *DiagObj; 1329 StringRef StoredDiagMessage; 1330 1331 public: 1332 explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {} 1333 Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage) 1334 : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {} 1335 1336 const DiagnosticsEngine *getDiags() const { return DiagObj; } 1337 unsigned getID() const { return DiagObj->CurDiagID; } 1338 const SourceLocation &getLocation() const { return DiagObj->CurDiagLoc; } 1339 bool hasSourceManager() const { return DiagObj->hasSourceManager(); } 1340 SourceManager &getSourceManager() const { return DiagObj->getSourceManager();} 1341 1342 unsigned getNumArgs() const { return DiagObj->NumDiagArgs; } 1343 1344 /// Return the kind of the specified index. 1345 /// 1346 /// Based on the kind of argument, the accessors below can be used to get 1347 /// the value. 1348 /// 1349 /// \pre Idx < getNumArgs() 1350 DiagnosticsEngine::ArgumentKind getArgKind(unsigned Idx) const { 1351 assert(Idx < getNumArgs() && "Argument index out of range!"); 1352 return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx]; 1353 } 1354 1355 /// Return the provided argument string specified by \p Idx. 1356 /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string 1357 const std::string &getArgStdStr(unsigned Idx) const { 1358 assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string && 1359 "invalid argument accessor!"); 1360 return DiagObj->DiagArgumentsStr[Idx]; 1361 } 1362 1363 /// Return the specified C string argument. 1364 /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string 1365 const char *getArgCStr(unsigned Idx) const { 1366 assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string && 1367 "invalid argument accessor!"); 1368 return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]); 1369 } 1370 1371 /// Return the specified signed integer argument. 1372 /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint 1373 int getArgSInt(unsigned Idx) const { 1374 assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint && 1375 "invalid argument accessor!"); 1376 return (int)DiagObj->DiagArgumentsVal[Idx]; 1377 } 1378 1379 /// Return the specified unsigned integer argument. 1380 /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint 1381 unsigned getArgUInt(unsigned Idx) const { 1382 assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint && 1383 "invalid argument accessor!"); 1384 return (unsigned)DiagObj->DiagArgumentsVal[Idx]; 1385 } 1386 1387 /// Return the specified IdentifierInfo argument. 1388 /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo 1389 const IdentifierInfo *getArgIdentifier(unsigned Idx) const { 1390 assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo && 1391 "invalid argument accessor!"); 1392 return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]); 1393 } 1394 1395 /// Return the specified non-string argument in an opaque form. 1396 /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string 1397 intptr_t getRawArg(unsigned Idx) const { 1398 assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string && 1399 "invalid argument accessor!"); 1400 return DiagObj->DiagArgumentsVal[Idx]; 1401 } 1402 1403 /// Return the number of source ranges associated with this diagnostic. 1404 unsigned getNumRanges() const { 1405 return DiagObj->DiagRanges.size(); 1406 } 1407 1408 /// \pre Idx < getNumRanges() 1409 const CharSourceRange &getRange(unsigned Idx) const { 1410 assert(Idx < getNumRanges() && "Invalid diagnostic range index!"); 1411 return DiagObj->DiagRanges[Idx]; 1412 } 1413 1414 /// Return an array reference for this diagnostic's ranges. 1415 ArrayRef<CharSourceRange> getRanges() const { 1416 return DiagObj->DiagRanges; 1417 } 1418 1419 unsigned getNumFixItHints() const { 1420 return DiagObj->DiagFixItHints.size(); 1421 } 1422 1423 const FixItHint &getFixItHint(unsigned Idx) const { 1424 assert(Idx < getNumFixItHints() && "Invalid index!"); 1425 return DiagObj->DiagFixItHints[Idx]; 1426 } 1427 1428 ArrayRef<FixItHint> getFixItHints() const { 1429 return DiagObj->DiagFixItHints; 1430 } 1431 1432 /// Format this diagnostic into a string, substituting the 1433 /// formal arguments into the %0 slots. 1434 /// 1435 /// The result is appended onto the \p OutStr array. 1436 void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const; 1437 1438 /// Format the given format-string into the output buffer using the 1439 /// arguments stored in this diagnostic. 1440 void FormatDiagnostic(const char *DiagStr, const char *DiagEnd, 1441 SmallVectorImpl<char> &OutStr) const; 1442 }; 1443 1444 /** 1445 * Represents a diagnostic in a form that can be retained until its 1446 * corresponding source manager is destroyed. 1447 */ 1448 class StoredDiagnostic { 1449 unsigned ID; 1450 DiagnosticsEngine::Level Level; 1451 FullSourceLoc Loc; 1452 std::string Message; 1453 std::vector<CharSourceRange> Ranges; 1454 std::vector<FixItHint> FixIts; 1455 1456 public: 1457 StoredDiagnostic() = default; 1458 StoredDiagnostic(DiagnosticsEngine::Level Level, const Diagnostic &Info); 1459 StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID, 1460 StringRef Message); 1461 StoredDiagnostic(DiagnosticsEngine::Level Level, unsigned ID, 1462 StringRef Message, FullSourceLoc Loc, 1463 ArrayRef<CharSourceRange> Ranges, 1464 ArrayRef<FixItHint> Fixits); 1465 1466 /// Evaluates true when this object stores a diagnostic. 1467 explicit operator bool() const { return !Message.empty(); } 1468 1469 unsigned getID() const { return ID; } 1470 DiagnosticsEngine::Level getLevel() const { return Level; } 1471 const FullSourceLoc &getLocation() const { return Loc; } 1472 StringRef getMessage() const { return Message; } 1473 1474 void setLocation(FullSourceLoc Loc) { this->Loc = Loc; } 1475 1476 using range_iterator = std::vector<CharSourceRange>::const_iterator; 1477 1478 range_iterator range_begin() const { return Ranges.begin(); } 1479 range_iterator range_end() const { return Ranges.end(); } 1480 unsigned range_size() const { return Ranges.size(); } 1481 1482 ArrayRef<CharSourceRange> getRanges() const { 1483 return llvm::makeArrayRef(Ranges); 1484 } 1485 1486 using fixit_iterator = std::vector<FixItHint>::const_iterator; 1487 1488 fixit_iterator fixit_begin() const { return FixIts.begin(); } 1489 fixit_iterator fixit_end() const { return FixIts.end(); } 1490 unsigned fixit_size() const { return FixIts.size(); } 1491 1492 ArrayRef<FixItHint> getFixIts() const { 1493 return llvm::makeArrayRef(FixIts); 1494 } 1495 }; 1496 1497 /// Abstract interface, implemented by clients of the front-end, which 1498 /// formats and prints fully processed diagnostics. 1499 class DiagnosticConsumer { 1500 protected: 1501 unsigned NumWarnings = 0; ///< Number of warnings reported 1502 unsigned NumErrors = 0; ///< Number of errors reported 1503 1504 public: 1505 DiagnosticConsumer() = default; 1506 virtual ~DiagnosticConsumer(); 1507 1508 unsigned getNumErrors() const { return NumErrors; } 1509 unsigned getNumWarnings() const { return NumWarnings; } 1510 virtual void clear() { NumWarnings = NumErrors = 0; } 1511 1512 /// Callback to inform the diagnostic client that processing 1513 /// of a source file is beginning. 1514 /// 1515 /// Note that diagnostics may be emitted outside the processing of a source 1516 /// file, for example during the parsing of command line options. However, 1517 /// diagnostics with source range information are required to only be emitted 1518 /// in between BeginSourceFile() and EndSourceFile(). 1519 /// 1520 /// \param LangOpts The language options for the source file being processed. 1521 /// \param PP The preprocessor object being used for the source; this is 1522 /// optional, e.g., it may not be present when processing AST source files. 1523 virtual void BeginSourceFile(const LangOptions &LangOpts, 1524 const Preprocessor *PP = nullptr) {} 1525 1526 /// Callback to inform the diagnostic client that processing 1527 /// of a source file has ended. 1528 /// 1529 /// The diagnostic client should assume that any objects made available via 1530 /// BeginSourceFile() are inaccessible. 1531 virtual void EndSourceFile() {} 1532 1533 /// Callback to inform the diagnostic client that processing of all 1534 /// source files has ended. 1535 virtual void finish() {} 1536 1537 /// Indicates whether the diagnostics handled by this 1538 /// DiagnosticConsumer should be included in the number of diagnostics 1539 /// reported by DiagnosticsEngine. 1540 /// 1541 /// The default implementation returns true. 1542 virtual bool IncludeInDiagnosticCounts() const; 1543 1544 /// Handle this diagnostic, reporting it to the user or 1545 /// capturing it to a log as needed. 1546 /// 1547 /// The default implementation just keeps track of the total number of 1548 /// warnings and errors. 1549 virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 1550 const Diagnostic &Info); 1551 }; 1552 1553 /// A diagnostic client that ignores all diagnostics. 1554 class IgnoringDiagConsumer : public DiagnosticConsumer { 1555 virtual void anchor(); 1556 1557 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 1558 const Diagnostic &Info) override { 1559 // Just ignore it. 1560 } 1561 }; 1562 1563 /// Diagnostic consumer that forwards diagnostics along to an 1564 /// existing, already-initialized diagnostic consumer. 1565 /// 1566 class ForwardingDiagnosticConsumer : public DiagnosticConsumer { 1567 DiagnosticConsumer &Target; 1568 1569 public: 1570 ForwardingDiagnosticConsumer(DiagnosticConsumer &Target) : Target(Target) {} 1571 ~ForwardingDiagnosticConsumer() override; 1572 1573 void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, 1574 const Diagnostic &Info) override; 1575 void clear() override; 1576 1577 bool IncludeInDiagnosticCounts() const override; 1578 }; 1579 1580 // Struct used for sending info about how a type should be printed. 1581 struct TemplateDiffTypes { 1582 intptr_t FromType; 1583 intptr_t ToType; 1584 unsigned PrintTree : 1; 1585 unsigned PrintFromType : 1; 1586 unsigned ElideType : 1; 1587 unsigned ShowColors : 1; 1588 1589 // The printer sets this variable to true if the template diff was used. 1590 unsigned TemplateDiffUsed : 1; 1591 }; 1592 1593 /// Special character that the diagnostic printer will use to toggle the bold 1594 /// attribute. The character itself will be not be printed. 1595 const char ToggleHighlight = 127; 1596 1597 /// ProcessWarningOptions - Initialize the diagnostic client and process the 1598 /// warning options specified on the command line. 1599 void ProcessWarningOptions(DiagnosticsEngine &Diags, 1600 const DiagnosticOptions &Opts, 1601 bool ReportDiags = true); 1602 1603 } // namespace clang 1604 1605 #endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H 1606