Diagnostic.h revision 91a2886d558ea6ca7a0bed73ab5acea5ae78eac2
1//===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This file defines the Diagnostic-related interfaces. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef LLVM_CLANG_DIAGNOSTIC_H 15#define LLVM_CLANG_DIAGNOSTIC_H 16 17#include "clang/Basic/SourceLocation.h" 18#include <string> 19#include <vector> 20#include <cassert> 21 22namespace llvm { 23 template <typename T> class SmallVectorImpl; 24} 25 26namespace clang { 27 class DiagnosticClient; 28 class SourceRange; 29 class DiagnosticBuilder; 30 class IdentifierInfo; 31 class LangOptions; 32 33 // Import the diagnostic enums themselves. 34 namespace diag { 35 // Start position for diagnostics. 36 enum { 37 DIAG_START_DRIVER = 300, 38 DIAG_START_FRONTEND = DIAG_START_DRIVER + 100, 39 DIAG_START_LEX = DIAG_START_FRONTEND + 100, 40 DIAG_START_PARSE = DIAG_START_LEX + 300, 41 DIAG_START_AST = DIAG_START_PARSE + 300, 42 DIAG_START_SEMA = DIAG_START_AST + 100, 43 DIAG_START_ANALYSIS = DIAG_START_SEMA + 1000, 44 DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100 45 }; 46 47 class CustomDiagInfo; 48 49 /// diag::kind - All of the diagnostics that can be emitted by the frontend. 50 typedef unsigned kind; 51 52 // Get typedefs for common diagnostics. 53 enum { 54#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE) ENUM, 55#include "clang/Basic/DiagnosticCommonKinds.inc" 56 NUM_BUILTIN_COMMON_DIAGNOSTICS 57#undef DIAG 58 }; 59 60 /// Enum values that allow the client to map NOTEs, WARNINGs, and EXTENSIONs 61 /// to either MAP_IGNORE (nothing), MAP_WARNING (emit a warning), MAP_ERROR 62 /// (emit as an error). It allows clients to map errors to 63 /// MAP_ERROR/MAP_DEFAULT or MAP_FATAL (stop emitting diagnostics after this 64 /// one). 65 enum Mapping { 66 // NOTE: 0 means "uncomputed". 67 MAP_IGNORE = 1, //< Map this diagnostic to nothing, ignore it. 68 MAP_WARNING = 2, //< Map this diagnostic to a warning. 69 MAP_ERROR = 3, //< Map this diagnostic to an error. 70 MAP_FATAL = 4, //< Map this diagnostic to a fatal error. 71 72 /// Map this diagnostic to "warning", but make it immune to -Werror. This 73 /// happens when you specify -Wno-error=foo. 74 MAP_WARNING_NO_WERROR = 5 75 }; 76 } 77 78/// \brief Annotates a diagnostic with some code that should be 79/// inserted, removed, or replaced to fix the problem. 80/// 81/// This kind of hint should be used when we are certain that the 82/// introduction, removal, or modification of a particular (small!) 83/// amount of code will correct a compilation error. The compiler 84/// should also provide full recovery from such errors, such that 85/// suppressing the diagnostic output can still result in successful 86/// compilation. 87class CodeModificationHint { 88public: 89 /// \brief Tokens that should be removed to correct the error. 90 SourceRange RemoveRange; 91 92 /// \brief The location at which we should insert code to correct 93 /// the error. 94 SourceLocation InsertionLoc; 95 96 /// \brief The actual code to insert at the insertion location, as a 97 /// string. 98 std::string CodeToInsert; 99 100 /// \brief Empty code modification hint, indicating that no code 101 /// modification is known. 102 CodeModificationHint() : RemoveRange(), InsertionLoc() { } 103 104 /// \brief Create a code modification hint that inserts the given 105 /// code string at a specific location. 106 static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc, 107 const std::string &Code) { 108 CodeModificationHint Hint; 109 Hint.InsertionLoc = InsertionLoc; 110 Hint.CodeToInsert = Code; 111 return Hint; 112 } 113 114 /// \brief Create a code modification hint that removes the given 115 /// source range. 116 static CodeModificationHint CreateRemoval(SourceRange RemoveRange) { 117 CodeModificationHint Hint; 118 Hint.RemoveRange = RemoveRange; 119 return Hint; 120 } 121 122 /// \brief Create a code modification hint that replaces the given 123 /// source range with the given code string. 124 static CodeModificationHint CreateReplacement(SourceRange RemoveRange, 125 const std::string &Code) { 126 CodeModificationHint Hint; 127 Hint.RemoveRange = RemoveRange; 128 Hint.InsertionLoc = RemoveRange.getBegin(); 129 Hint.CodeToInsert = Code; 130 return Hint; 131 } 132}; 133 134/// Diagnostic - This concrete class is used by the front-end to report 135/// problems and issues. It massages the diagnostics (e.g. handling things like 136/// "report warnings as errors" and passes them off to the DiagnosticClient for 137/// reporting to the user. 138class Diagnostic { 139public: 140 /// Level - The level of the diagnostic, after it has been through mapping. 141 enum Level { 142 Ignored, Note, Warning, Error, Fatal 143 }; 144 145 /// ExtensionHandling - How do we handle otherwise-unmapped extension? This 146 /// is controlled by -pedantic and -pedantic-errors. 147 enum ExtensionHandling { 148 Ext_Ignore, Ext_Warn, Ext_Error 149 }; 150 151 enum ArgumentKind { 152 ak_std_string, // std::string 153 ak_c_string, // const char * 154 ak_sint, // int 155 ak_uint, // unsigned 156 ak_identifierinfo, // IdentifierInfo 157 ak_qualtype, // QualType 158 ak_declarationname, // DeclarationName 159 ak_nameddecl, // NamedDecl * 160 ak_nestednamespec // NestedNameSpecifier * 161 }; 162 163private: 164 unsigned char AllExtensionsSilenced; // Used by __extension__ 165 bool IgnoreAllWarnings; // Ignore all warnings: -w 166 bool WarningsAsErrors; // Treat warnings like errors: 167 bool SuppressSystemWarnings; // Suppress warnings in system headers. 168 ExtensionHandling ExtBehavior; // Map extensions onto warnings or errors? 169 DiagnosticClient *Client; 170 171 /// DiagMappings - Mapping information for diagnostics. Mapping info is 172 /// packed into four bits per diagnostic. The low three bits are the mapping 173 /// (an instance of diag::Mapping), or zero if unset. The high bit is set 174 /// when the mapping was established as a user mapping. If the high bit is 175 /// clear, then the low bits are set to the default value, and should be 176 /// mapped with -pedantic, -Werror, etc. 177 178 typedef std::vector<unsigned char> DiagMappings; 179 mutable std::vector<DiagMappings> DiagMappingsStack; 180 181 /// ErrorOccurred / FatalErrorOccurred - This is set to true when an error or 182 /// fatal error is emitted, and is sticky. 183 bool ErrorOccurred; 184 bool FatalErrorOccurred; 185 186 /// LastDiagLevel - This is the level of the last diagnostic emitted. This is 187 /// used to emit continuation diagnostics with the same level as the 188 /// diagnostic that they follow. 189 Diagnostic::Level LastDiagLevel; 190 191 unsigned NumDiagnostics; // Number of diagnostics reported 192 unsigned NumErrors; // Number of diagnostics that are errors 193 194 /// CustomDiagInfo - Information for uniquing and looking up custom diags. 195 diag::CustomDiagInfo *CustomDiagInfo; 196 197 /// ArgToStringFn - A function pointer that converts an opaque diagnostic 198 /// argument to a strings. This takes the modifiers and argument that was 199 /// present in the diagnostic. 200 /// This is a hack to avoid a layering violation between libbasic and libsema. 201 typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val, 202 const char *Modifier, unsigned ModifierLen, 203 const char *Argument, unsigned ArgumentLen, 204 llvm::SmallVectorImpl<char> &Output, 205 void *Cookie); 206 void *ArgToStringCookie; 207 ArgToStringFnTy ArgToStringFn; 208public: 209 explicit Diagnostic(DiagnosticClient *client = 0); 210 ~Diagnostic(); 211 212 //===--------------------------------------------------------------------===// 213 // Diagnostic characterization methods, used by a client to customize how 214 // 215 216 DiagnosticClient *getClient() { return Client; }; 217 const DiagnosticClient *getClient() const { return Client; }; 218 219 220 /// pushMappings - Copies the current DiagMappings and pushes the new copy 221 /// onto the top of the stack. 222 void pushMappings(); 223 224 /// popMappings - Pops the current DiagMappings off the top of the stack 225 /// causing the new top of the stack to be the active mappings. Returns 226 /// true if the pop happens, false if there is only one DiagMapping on the 227 /// stack. 228 bool popMappings(); 229 230 void setClient(DiagnosticClient* client) { Client = client; } 231 232 /// setIgnoreAllWarnings - When set to true, any unmapped warnings are 233 /// ignored. If this and WarningsAsErrors are both set, then this one wins. 234 void setIgnoreAllWarnings(bool Val) { IgnoreAllWarnings = Val; } 235 bool getIgnoreAllWarnings() const { return IgnoreAllWarnings; } 236 237 /// setWarningsAsErrors - When set to true, any warnings reported are issued 238 /// as errors. 239 void setWarningsAsErrors(bool Val) { WarningsAsErrors = Val; } 240 bool getWarningsAsErrors() const { return WarningsAsErrors; } 241 242 /// setSuppressSystemWarnings - When set to true mask warnings that 243 /// come from system headers. 244 void setSuppressSystemWarnings(bool Val) { SuppressSystemWarnings = Val; } 245 bool getSuppressSystemWarnings() const { return SuppressSystemWarnings; } 246 247 /// setExtensionHandlingBehavior - This controls whether otherwise-unmapped 248 /// extension diagnostics are mapped onto ignore/warning/error. This 249 /// corresponds to the GCC -pedantic and -pedantic-errors option. 250 void setExtensionHandlingBehavior(ExtensionHandling H) { 251 ExtBehavior = H; 252 } 253 254 /// AllExtensionsSilenced - This is a counter bumped when an __extension__ 255 /// block is encountered. When non-zero, all extension diagnostics are 256 /// entirely silenced, no matter how they are mapped. 257 void IncrementAllExtensionsSilenced() { ++AllExtensionsSilenced; } 258 void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; } 259 bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; } 260 261 /// setDiagnosticMapping - This allows the client to specify that certain 262 /// warnings are ignored. Notes can never be mapped, errors can only be 263 /// mapped to fatal, and WARNINGs and EXTENSIONs can be mapped arbitrarily. 264 void setDiagnosticMapping(diag::kind Diag, diag::Mapping Map) { 265 assert(Diag < diag::DIAG_UPPER_LIMIT && 266 "Can only map builtin diagnostics"); 267 assert((isBuiltinWarningOrExtension(Diag) || Map == diag::MAP_FATAL) && 268 "Cannot map errors!"); 269 setDiagnosticMappingInternal(Diag, Map, true); 270 } 271 272 /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g. 273 /// "unknown-pragmas" to have the specified mapping. This returns true and 274 /// ignores the request if "Group" was unknown, false otherwise. 275 bool setDiagnosticGroupMapping(const char *Group, diag::Mapping Map); 276 277 bool hasErrorOccurred() const { return ErrorOccurred; } 278 bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } 279 280 unsigned getNumErrors() const { return NumErrors; } 281 unsigned getNumDiagnostics() const { return NumDiagnostics; } 282 283 /// getCustomDiagID - Return an ID for a diagnostic with the specified message 284 /// and level. If this is the first request for this diagnosic, it is 285 /// registered and created, otherwise the existing ID is returned. 286 unsigned getCustomDiagID(Level L, const char *Message); 287 288 289 /// ConvertArgToString - This method converts a diagnostic argument (as an 290 /// intptr_t) into the string that represents it. 291 void ConvertArgToString(ArgumentKind Kind, intptr_t Val, 292 const char *Modifier, unsigned ModLen, 293 const char *Argument, unsigned ArgLen, 294 llvm::SmallVectorImpl<char> &Output) const { 295 ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, Output, 296 ArgToStringCookie); 297 } 298 299 void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { 300 ArgToStringFn = Fn; 301 ArgToStringCookie = Cookie; 302 } 303 304 //===--------------------------------------------------------------------===// 305 // Diagnostic classification and reporting interfaces. 306 // 307 308 /// getDescription - Given a diagnostic ID, return a description of the 309 /// issue. 310 const char *getDescription(unsigned DiagID) const; 311 312 /// isNoteWarningOrExtension - Return true if the unmapped diagnostic 313 /// level of the specified diagnostic ID is a Warning or Extension. 314 /// This only works on builtin diagnostics, not custom ones, and is not legal to 315 /// call on NOTEs. 316 static bool isBuiltinWarningOrExtension(unsigned DiagID); 317 318 /// \brief Determine whether the given built-in diagnostic ID is a 319 /// Note. 320 static bool isBuiltinNote(unsigned DiagID); 321 322 /// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic 323 /// ID is for an extension of some sort. 324 /// 325 static bool isBuiltinExtensionDiag(unsigned DiagID); 326 327 /// getWarningOptionForDiag - Return the lowest-level warning option that 328 /// enables the specified diagnostic. If there is no -Wfoo flag that controls 329 /// the diagnostic, this returns null. 330 static const char *getWarningOptionForDiag(unsigned DiagID); 331 332 /// \brief Determines whether the given built-in diagnostic ID is 333 /// for an error that is suppressed if it occurs during C++ template 334 /// argument deduction. 335 /// 336 /// When an error is suppressed due to SFINAE, the template argument 337 /// deduction fails but no diagnostic is emitted. Certain classes of 338 /// errors, such as those errors that involve C++ access control, 339 /// are not SFINAE errors. 340 static bool isBuiltinSFINAEDiag(unsigned DiagID); 341 342 /// getDiagnosticLevel - Based on the way the client configured the Diagnostic 343 /// object, classify the specified diagnostic ID into a Level, consumable by 344 /// the DiagnosticClient. 345 Level getDiagnosticLevel(unsigned DiagID) const; 346 347 /// Report - Issue the message to the client. @c DiagID is a member of the 348 /// @c diag::kind enum. This actually returns aninstance of DiagnosticBuilder 349 /// which emits the diagnostics (through @c ProcessDiag) when it is destroyed. 350 /// @c Pos represents the source location associated with the diagnostic, 351 /// which can be an invalid location if no position information is available. 352 inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID); 353 354 /// \brief Clear out the current diagnostic. 355 void Clear() { CurDiagID = ~0U; } 356 357private: 358 /// getDiagnosticMappingInfo - Return the mapping info currently set for the 359 /// specified builtin diagnostic. This returns the high bit encoding, or zero 360 /// if the field is completely uninitialized. 361 unsigned getDiagnosticMappingInfo(diag::kind Diag) const { 362 const DiagMappings ¤tMappings = DiagMappingsStack.back(); 363 return (diag::Mapping)((currentMappings[Diag/2] >> (Diag & 1)*4) & 15); 364 } 365 366 void setDiagnosticMappingInternal(unsigned DiagId, unsigned Map, 367 bool isUser) const { 368 if (isUser) Map |= 8; // Set the high bit for user mappings. 369 unsigned char &Slot = DiagMappingsStack.back()[DiagId/2]; 370 unsigned Shift = (DiagId & 1)*4; 371 Slot &= ~(15 << Shift); 372 Slot |= Map << Shift; 373 } 374 375 /// getDiagnosticLevel - This is an internal implementation helper used when 376 /// DiagClass is already known. 377 Level getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const; 378 379 // This is private state used by DiagnosticBuilder. We put it here instead of 380 // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight 381 // object. This implementation choice means that we can only have one 382 // diagnostic "in flight" at a time, but this seems to be a reasonable 383 // tradeoff to keep these objects small. Assertions verify that only one 384 // diagnostic is in flight at a time. 385 friend class DiagnosticBuilder; 386 friend class DiagnosticInfo; 387 388 /// CurDiagLoc - This is the location of the current diagnostic that is in 389 /// flight. 390 FullSourceLoc CurDiagLoc; 391 392 /// CurDiagID - This is the ID of the current diagnostic that is in flight. 393 /// This is set to ~0U when there is no diagnostic in flight. 394 unsigned CurDiagID; 395 396 enum { 397 /// MaxArguments - The maximum number of arguments we can hold. We currently 398 /// only support up to 10 arguments (%0-%9). A single diagnostic with more 399 /// than that almost certainly has to be simplified anyway. 400 MaxArguments = 10 401 }; 402 403 /// NumDiagArgs - This contains the number of entries in Arguments. 404 signed char NumDiagArgs; 405 /// NumRanges - This is the number of ranges in the DiagRanges array. 406 unsigned char NumDiagRanges; 407 /// \brief The number of code modifications hints in the 408 /// CodeModificationHints array. 409 unsigned char NumCodeModificationHints; 410 411 /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum 412 /// values, with one for each argument. This specifies whether the argument 413 /// is in DiagArgumentsStr or in DiagArguments. 414 unsigned char DiagArgumentsKind[MaxArguments]; 415 416 /// DiagArgumentsStr - This holds the values of each string argument for the 417 /// current diagnostic. This value is only used when the corresponding 418 /// ArgumentKind is ak_std_string. 419 std::string DiagArgumentsStr[MaxArguments]; 420 421 /// DiagArgumentsVal - The values for the various substitution positions. This 422 /// is used when the argument is not an std::string. The specific value is 423 /// mangled into an intptr_t and the intepretation depends on exactly what 424 /// sort of argument kind it is. 425 intptr_t DiagArgumentsVal[MaxArguments]; 426 427 /// DiagRanges - The list of ranges added to this diagnostic. It currently 428 /// only support 10 ranges, could easily be extended if needed. 429 const SourceRange *DiagRanges[10]; 430 431 enum { MaxCodeModificationHints = 3 }; 432 433 /// CodeModificationHints - If valid, provides a hint with some code 434 /// to insert, remove, or modify at a particular position. 435 CodeModificationHint CodeModificationHints[MaxCodeModificationHints]; 436 437 /// ProcessDiag - This is the method used to report a diagnostic that is 438 /// finally fully formed. 439 /// 440 /// \returns true if the diagnostic was emitted, false if it was 441 /// suppressed. 442 bool ProcessDiag(); 443}; 444 445//===----------------------------------------------------------------------===// 446// DiagnosticBuilder 447//===----------------------------------------------------------------------===// 448 449/// DiagnosticBuilder - This is a little helper class used to produce 450/// diagnostics. This is constructed by the Diagnostic::Report method, and 451/// allows insertion of extra information (arguments and source ranges) into the 452/// currently "in flight" diagnostic. When the temporary for the builder is 453/// destroyed, the diagnostic is issued. 454/// 455/// Note that many of these will be created as temporary objects (many call 456/// sites), so we want them to be small and we never want their address taken. 457/// This ensures that compilers with somewhat reasonable optimizers will promote 458/// the common fields to registers, eliminating increments of the NumArgs field, 459/// for example. 460class DiagnosticBuilder { 461 mutable Diagnostic *DiagObj; 462 mutable unsigned NumArgs, NumRanges, NumCodeModificationHints; 463 464 void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT 465 friend class Diagnostic; 466 explicit DiagnosticBuilder(Diagnostic *diagObj) 467 : DiagObj(diagObj), NumArgs(0), NumRanges(0), 468 NumCodeModificationHints(0) {} 469 470public: 471 /// Copy constructor. When copied, this "takes" the diagnostic info from the 472 /// input and neuters it. 473 DiagnosticBuilder(const DiagnosticBuilder &D) { 474 DiagObj = D.DiagObj; 475 D.DiagObj = 0; 476 NumArgs = D.NumArgs; 477 NumRanges = D.NumRanges; 478 NumCodeModificationHints = D.NumCodeModificationHints; 479 } 480 481 /// \brief Simple enumeration value used to give a name to the 482 /// suppress-diagnostic constructor. 483 enum SuppressKind { Suppress }; 484 485 /// \brief Create an empty DiagnosticBuilder object that represents 486 /// no actual diagnostic. 487 explicit DiagnosticBuilder(SuppressKind) 488 : DiagObj(0), NumArgs(0), NumRanges(0), NumCodeModificationHints(0) { } 489 490 /// \brief Force the diagnostic builder to emit the diagnostic now. 491 /// 492 /// Once this function has been called, the DiagnosticBuilder object 493 /// should not be used again before it is destroyed. 494 /// 495 /// \returns true if a diagnostic was emitted, false if the 496 /// diagnostic was suppressed. 497 bool Emit() { 498 // If DiagObj is null, then its soul was stolen by the copy ctor 499 // or the user called Emit(). 500 if (DiagObj == 0) return false; 501 502 // When emitting diagnostics, we set the final argument count into 503 // the Diagnostic object. 504 DiagObj->NumDiagArgs = NumArgs; 505 DiagObj->NumDiagRanges = NumRanges; 506 DiagObj->NumCodeModificationHints = NumCodeModificationHints; 507 508 // Process the diagnostic, sending the accumulated information to the 509 // DiagnosticClient. 510 bool Emitted = DiagObj->ProcessDiag(); 511 512 // Clear out the current diagnostic object. 513 DiagObj->Clear(); 514 515 // This diagnostic is dead. 516 DiagObj = 0; 517 518 return Emitted; 519 } 520 521 /// Destructor - The dtor emits the diagnostic if it hasn't already 522 /// been emitted. 523 ~DiagnosticBuilder() { Emit(); } 524 525 /// Operator bool: conversion of DiagnosticBuilder to bool always returns 526 /// true. This allows is to be used in boolean error contexts like: 527 /// return Diag(...); 528 operator bool() const { return true; } 529 530 void AddString(const std::string &S) const { 531 assert(NumArgs < Diagnostic::MaxArguments && 532 "Too many arguments to diagnostic!"); 533 if (DiagObj) { 534 DiagObj->DiagArgumentsKind[NumArgs] = Diagnostic::ak_std_string; 535 DiagObj->DiagArgumentsStr[NumArgs++] = S; 536 } 537 } 538 539 void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const { 540 assert(NumArgs < Diagnostic::MaxArguments && 541 "Too many arguments to diagnostic!"); 542 if (DiagObj) { 543 DiagObj->DiagArgumentsKind[NumArgs] = Kind; 544 DiagObj->DiagArgumentsVal[NumArgs++] = V; 545 } 546 } 547 548 void AddSourceRange(const SourceRange &R) const { 549 assert(NumRanges < 550 sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) && 551 "Too many arguments to diagnostic!"); 552 if (DiagObj) 553 DiagObj->DiagRanges[NumRanges++] = &R; 554 } 555 556 void AddCodeModificationHint(const CodeModificationHint &Hint) const { 557 assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints && 558 "Too many code modification hints!"); 559 if (DiagObj) 560 DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint; 561 } 562}; 563 564inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 565 const std::string &S) { 566 DB.AddString(S); 567 return DB; 568} 569 570inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 571 const char *Str) { 572 DB.AddTaggedVal(reinterpret_cast<intptr_t>(Str), 573 Diagnostic::ak_c_string); 574 return DB; 575} 576 577inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, int I) { 578 DB.AddTaggedVal(I, Diagnostic::ak_sint); 579 return DB; 580} 581 582inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,bool I) { 583 DB.AddTaggedVal(I, Diagnostic::ak_sint); 584 return DB; 585} 586 587inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 588 unsigned I) { 589 DB.AddTaggedVal(I, Diagnostic::ak_uint); 590 return DB; 591} 592 593inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 594 const IdentifierInfo *II) { 595 DB.AddTaggedVal(reinterpret_cast<intptr_t>(II), 596 Diagnostic::ak_identifierinfo); 597 return DB; 598} 599 600inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 601 const SourceRange &R) { 602 DB.AddSourceRange(R); 603 return DB; 604} 605 606inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, 607 const CodeModificationHint &Hint) { 608 DB.AddCodeModificationHint(Hint); 609 return DB; 610} 611 612/// Report - Issue the message to the client. DiagID is a member of the 613/// diag::kind enum. This actually returns a new instance of DiagnosticBuilder 614/// which emits the diagnostics (through ProcessDiag) when it is destroyed. 615inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){ 616 assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!"); 617 CurDiagLoc = Loc; 618 CurDiagID = DiagID; 619 return DiagnosticBuilder(this); 620} 621 622//===----------------------------------------------------------------------===// 623// DiagnosticInfo 624//===----------------------------------------------------------------------===// 625 626/// DiagnosticInfo - This is a little helper class (which is basically a smart 627/// pointer that forward info from Diagnostic) that allows clients to enquire 628/// about the currently in-flight diagnostic. 629class DiagnosticInfo { 630 const Diagnostic *DiagObj; 631public: 632 explicit DiagnosticInfo(const Diagnostic *DO) : DiagObj(DO) {} 633 634 const Diagnostic *getDiags() const { return DiagObj; } 635 unsigned getID() const { return DiagObj->CurDiagID; } 636 const FullSourceLoc &getLocation() const { return DiagObj->CurDiagLoc; } 637 638 unsigned getNumArgs() const { return DiagObj->NumDiagArgs; } 639 640 /// getArgKind - Return the kind of the specified index. Based on the kind 641 /// of argument, the accessors below can be used to get the value. 642 Diagnostic::ArgumentKind getArgKind(unsigned Idx) const { 643 assert(Idx < getNumArgs() && "Argument index out of range!"); 644 return (Diagnostic::ArgumentKind)DiagObj->DiagArgumentsKind[Idx]; 645 } 646 647 /// getArgStdStr - Return the provided argument string specified by Idx. 648 const std::string &getArgStdStr(unsigned Idx) const { 649 assert(getArgKind(Idx) == Diagnostic::ak_std_string && 650 "invalid argument accessor!"); 651 return DiagObj->DiagArgumentsStr[Idx]; 652 } 653 654 /// getArgCStr - Return the specified C string argument. 655 const char *getArgCStr(unsigned Idx) const { 656 assert(getArgKind(Idx) == Diagnostic::ak_c_string && 657 "invalid argument accessor!"); 658 return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]); 659 } 660 661 /// getArgSInt - Return the specified signed integer argument. 662 int getArgSInt(unsigned Idx) const { 663 assert(getArgKind(Idx) == Diagnostic::ak_sint && 664 "invalid argument accessor!"); 665 return (int)DiagObj->DiagArgumentsVal[Idx]; 666 } 667 668 /// getArgUInt - Return the specified unsigned integer argument. 669 unsigned getArgUInt(unsigned Idx) const { 670 assert(getArgKind(Idx) == Diagnostic::ak_uint && 671 "invalid argument accessor!"); 672 return (unsigned)DiagObj->DiagArgumentsVal[Idx]; 673 } 674 675 /// getArgIdentifier - Return the specified IdentifierInfo argument. 676 const IdentifierInfo *getArgIdentifier(unsigned Idx) const { 677 assert(getArgKind(Idx) == Diagnostic::ak_identifierinfo && 678 "invalid argument accessor!"); 679 return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]); 680 } 681 682 /// getRawArg - Return the specified non-string argument in an opaque form. 683 intptr_t getRawArg(unsigned Idx) const { 684 assert(getArgKind(Idx) != Diagnostic::ak_std_string && 685 "invalid argument accessor!"); 686 return DiagObj->DiagArgumentsVal[Idx]; 687 } 688 689 690 /// getNumRanges - Return the number of source ranges associated with this 691 /// diagnostic. 692 unsigned getNumRanges() const { 693 return DiagObj->NumDiagRanges; 694 } 695 696 const SourceRange &getRange(unsigned Idx) const { 697 assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!"); 698 return *DiagObj->DiagRanges[Idx]; 699 } 700 701 unsigned getNumCodeModificationHints() const { 702 return DiagObj->NumCodeModificationHints; 703 } 704 705 const CodeModificationHint &getCodeModificationHint(unsigned Idx) const { 706 return DiagObj->CodeModificationHints[Idx]; 707 } 708 709 const CodeModificationHint *getCodeModificationHints() const { 710 return DiagObj->NumCodeModificationHints? 711 &DiagObj->CodeModificationHints[0] : 0; 712 } 713 714 /// FormatDiagnostic - Format this diagnostic into a string, substituting the 715 /// formal arguments into the %0 slots. The result is appended onto the Str 716 /// array. 717 void FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const; 718}; 719 720/// DiagnosticClient - This is an abstract interface implemented by clients of 721/// the front-end, which formats and prints fully processed diagnostics. 722class DiagnosticClient { 723public: 724 virtual ~DiagnosticClient(); 725 726 /// setLangOptions - This is set by clients of diagnostics when they know the 727 /// language parameters of the diagnostics that may be sent through. Note 728 /// that this can change over time if a DiagClient has multiple languages sent 729 /// through it. It may also be set to null (e.g. when processing command line 730 /// options). 731 virtual void setLangOptions(const LangOptions *LO) {} 732 733 /// IncludeInDiagnosticCounts - This method (whose default implementation 734 /// returns true) indicates whether the diagnostics handled by this 735 /// DiagnosticClient should be included in the number of diagnostics 736 /// reported by Diagnostic. 737 virtual bool IncludeInDiagnosticCounts() const; 738 739 /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or 740 /// capturing it to a log as needed. 741 virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, 742 const DiagnosticInfo &Info) = 0; 743}; 744 745} // end namespace clang 746 747#endif 748