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