Diagnostic.cpp revision a7e1898e6b84ed7911d1f25c975b27b78a4950cb
1//===--- Diagnostic.cpp - C Language Family Diagnostic Handling -----------===// 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 implements the Diagnostic-related interfaces. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/Basic/Diagnostic.h" 15 16#include "clang/Lex/LexDiagnostic.h" 17#include "clang/Parse/ParseDiagnostic.h" 18#include "clang/AST/ASTDiagnostic.h" 19#include "clang/Sema/SemaDiagnostic.h" 20#include "clang/Frontend/FrontendDiagnostic.h" 21#include "clang/Analysis/AnalysisDiagnostic.h" 22#include "clang/Driver/DriverDiagnostic.h" 23 24#include "clang/Basic/IdentifierTable.h" 25#include "clang/Basic/SourceLocation.h" 26#include "llvm/ADT/SmallVector.h" 27#include "llvm/ADT/StringExtras.h" 28#include <vector> 29#include <map> 30#include <cstring> 31using namespace clang; 32 33//===----------------------------------------------------------------------===// 34// Builtin Diagnostic information 35//===----------------------------------------------------------------------===// 36 37// Diagnostic classes. 38enum { 39 CLASS_NOTE = 0x01, 40 CLASS_WARNING = 0x02, 41 CLASS_EXTENSION = 0x03, 42 CLASS_ERROR = 0x04 43}; 44 45struct StaticDiagInfoRec { 46 unsigned short DiagID; 47 unsigned Mapping : 3; 48 unsigned Class : 3; 49 const char *Description; 50 const char *OptionGroup; 51 52 bool operator<(const StaticDiagInfoRec &RHS) const { 53 return DiagID < RHS.DiagID; 54 } 55 bool operator>(const StaticDiagInfoRec &RHS) const { 56 return DiagID > RHS.DiagID; 57 } 58}; 59 60static const StaticDiagInfoRec StaticDiagInfo[] = { 61#define DIAG(ENUM,CLASS,DEFAULT_MAPPING,DESC,GROUP) \ 62 { diag::ENUM, DEFAULT_MAPPING, CLASS, DESC, GROUP }, 63#include "clang/Basic/DiagnosticCommonKinds.inc" 64#include "clang/Basic/DiagnosticDriverKinds.inc" 65#include "clang/Basic/DiagnosticFrontendKinds.inc" 66#include "clang/Basic/DiagnosticLexKinds.inc" 67#include "clang/Basic/DiagnosticParseKinds.inc" 68#include "clang/Basic/DiagnosticASTKinds.inc" 69#include "clang/Basic/DiagnosticSemaKinds.inc" 70#include "clang/Basic/DiagnosticAnalysisKinds.inc" 71{ 0, 0, 0, 0, 0 } 72}; 73#undef DIAG 74 75/// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID, 76/// or null if the ID is invalid. 77static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) { 78 unsigned NumDiagEntries = sizeof(StaticDiagInfo)/sizeof(StaticDiagInfo[0])-1; 79 80 // If assertions are enabled, verify that the StaticDiagInfo array is sorted. 81#ifndef NDEBUG 82 static bool IsFirst = true; 83 if (IsFirst) { 84 for (unsigned i = 1; i != NumDiagEntries; ++i) 85 assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] && 86 "Improperly sorted diag info"); 87 IsFirst = false; 88 } 89#endif 90 91 // Search the diagnostic table with a binary search. 92 StaticDiagInfoRec Find = { DiagID, 0, 0, 0, 0 }; 93 94 const StaticDiagInfoRec *Found = 95 std::lower_bound(StaticDiagInfo, StaticDiagInfo + NumDiagEntries, Find); 96 if (Found == StaticDiagInfo + NumDiagEntries || 97 Found->DiagID != DiagID) 98 return 0; 99 100 return Found; 101} 102 103static unsigned GetDefaultDiagMapping(unsigned DiagID) { 104 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 105 return Info->Mapping; 106 return diag::MAP_FATAL; 107} 108 109/// getWarningOptionForDiag - Return the lowest-level warning option that 110/// enables the specified diagnostic. If there is no -Wfoo flag that controls 111/// the diagnostic, this returns null. 112const char *Diagnostic::getWarningOptionForDiag(unsigned DiagID) { 113 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 114 return Info->OptionGroup; 115 return 0; 116} 117 118/// getDiagClass - Return the class field of the diagnostic. 119/// 120static unsigned getBuiltinDiagClass(unsigned DiagID) { 121 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 122 return Info->Class; 123 return ~0U; 124} 125 126//===----------------------------------------------------------------------===// 127// Custom Diagnostic information 128//===----------------------------------------------------------------------===// 129 130namespace clang { 131 namespace diag { 132 class CustomDiagInfo { 133 typedef std::pair<Diagnostic::Level, std::string> DiagDesc; 134 std::vector<DiagDesc> DiagInfo; 135 std::map<DiagDesc, unsigned> DiagIDs; 136 public: 137 138 /// getDescription - Return the description of the specified custom 139 /// diagnostic. 140 const char *getDescription(unsigned DiagID) const { 141 assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() && 142 "Invalid diagnosic ID"); 143 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].second.c_str(); 144 } 145 146 /// getLevel - Return the level of the specified custom diagnostic. 147 Diagnostic::Level getLevel(unsigned DiagID) const { 148 assert(this && DiagID-DIAG_UPPER_LIMIT < DiagInfo.size() && 149 "Invalid diagnosic ID"); 150 return DiagInfo[DiagID-DIAG_UPPER_LIMIT].first; 151 } 152 153 unsigned getOrCreateDiagID(Diagnostic::Level L, const char *Message, 154 Diagnostic &Diags) { 155 DiagDesc D(L, Message); 156 // Check to see if it already exists. 157 std::map<DiagDesc, unsigned>::iterator I = DiagIDs.lower_bound(D); 158 if (I != DiagIDs.end() && I->first == D) 159 return I->second; 160 161 // If not, assign a new ID. 162 unsigned ID = DiagInfo.size()+DIAG_UPPER_LIMIT; 163 DiagIDs.insert(std::make_pair(D, ID)); 164 DiagInfo.push_back(D); 165 return ID; 166 } 167 }; 168 169 } // end diag namespace 170} // end clang namespace 171 172 173//===----------------------------------------------------------------------===// 174// Common Diagnostic implementation 175//===----------------------------------------------------------------------===// 176 177static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT, 178 const char *Modifier, unsigned ML, 179 const char *Argument, unsigned ArgLen, 180 llvm::SmallVectorImpl<char> &Output, 181 void *Cookie) { 182 const char *Str = "<can't format argument>"; 183 Output.append(Str, Str+strlen(Str)); 184} 185 186 187Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) { 188 AllExtensionsSilenced = 0; 189 IgnoreAllWarnings = false; 190 WarningsAsErrors = false; 191 SuppressSystemWarnings = false; 192 ExtBehavior = Ext_Ignore; 193 194 ErrorOccurred = false; 195 FatalErrorOccurred = false; 196 NumDiagnostics = 0; 197 NumErrors = 0; 198 CustomDiagInfo = 0; 199 CurDiagID = ~0U; 200 LastDiagLevel = Ignored; 201 202 ArgToStringFn = DummyArgToStringFn; 203 ArgToStringCookie = 0; 204 205 // Set all mappings to 'unset'. 206 memset(DiagMappings, 0, sizeof(DiagMappings)); 207} 208 209Diagnostic::~Diagnostic() { 210 delete CustomDiagInfo; 211} 212 213/// getCustomDiagID - Return an ID for a diagnostic with the specified message 214/// and level. If this is the first request for this diagnosic, it is 215/// registered and created, otherwise the existing ID is returned. 216unsigned Diagnostic::getCustomDiagID(Level L, const char *Message) { 217 if (CustomDiagInfo == 0) 218 CustomDiagInfo = new diag::CustomDiagInfo(); 219 return CustomDiagInfo->getOrCreateDiagID(L, Message, *this); 220} 221 222 223/// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic 224/// level of the specified diagnostic ID is a Warning or Extension. 225/// This only works on builtin diagnostics, not custom ones, and is not legal to 226/// call on NOTEs. 227bool Diagnostic::isBuiltinWarningOrExtension(unsigned DiagID) { 228 return DiagID < diag::DIAG_UPPER_LIMIT && 229 getBuiltinDiagClass(DiagID) != CLASS_ERROR; 230} 231 232/// \brief Determine whether the given built-in diagnostic ID is a 233/// Note. 234bool Diagnostic::isBuiltinNote(unsigned DiagID) { 235 return DiagID < diag::DIAG_UPPER_LIMIT && 236 getBuiltinDiagClass(DiagID) == CLASS_NOTE; 237} 238 239/// isBuiltinExtensionDiag - Determine whether the given built-in diagnostic 240/// ID is for an extension of some sort. 241/// 242bool Diagnostic::isBuiltinExtensionDiag(unsigned DiagID) { 243 return DiagID < diag::DIAG_UPPER_LIMIT && 244 getBuiltinDiagClass(DiagID) == CLASS_EXTENSION; 245} 246 247 248/// getDescription - Given a diagnostic ID, return a description of the 249/// issue. 250const char *Diagnostic::getDescription(unsigned DiagID) const { 251 if (const StaticDiagInfoRec *Info = GetDiagInfo(DiagID)) 252 return Info->Description; 253 return CustomDiagInfo->getDescription(DiagID); 254} 255 256/// getDiagnosticLevel - Based on the way the client configured the Diagnostic 257/// object, classify the specified diagnostic ID into a Level, consumable by 258/// the DiagnosticClient. 259Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const { 260 // Handle custom diagnostics, which cannot be mapped. 261 if (DiagID >= diag::DIAG_UPPER_LIMIT) 262 return CustomDiagInfo->getLevel(DiagID); 263 264 unsigned DiagClass = getBuiltinDiagClass(DiagID); 265 assert(DiagClass != CLASS_NOTE && "Cannot get diagnostic level of a note!"); 266 return getDiagnosticLevel(DiagID, DiagClass); 267} 268 269/// getDiagnosticLevel - Based on the way the client configured the Diagnostic 270/// object, classify the specified diagnostic ID into a Level, consumable by 271/// the DiagnosticClient. 272Diagnostic::Level 273Diagnostic::getDiagnosticLevel(unsigned DiagID, unsigned DiagClass) const { 274 // Specific non-error diagnostics may be mapped to various levels from ignored 275 // to error. Errors can only be mapped to fatal. 276 Diagnostic::Level Result = Diagnostic::Fatal; 277 278 // Get the mapping information, if unset, compute it lazily. 279 unsigned MappingInfo = getDiagnosticMappingInfo((diag::kind)DiagID); 280 if (MappingInfo == 0) { 281 MappingInfo = GetDefaultDiagMapping(DiagID); 282 setDiagnosticMappingInternal(DiagID, MappingInfo, false); 283 } 284 285 switch (MappingInfo & 7) { 286 default: assert(0 && "Unknown mapping!"); 287 case diag::MAP_IGNORE: 288 // Ignore this, unless this is an extension diagnostic and we're mapping 289 // them onto warnings or errors. 290 if (!isBuiltinExtensionDiag(DiagID) || // Not an extension 291 ExtBehavior == Ext_Ignore || // Extensions ignored anyway 292 (MappingInfo & 8) != 0) // User explicitly mapped it. 293 return Diagnostic::Ignored; 294 Result = Diagnostic::Warning; 295 if (ExtBehavior == Ext_Error) Result = Diagnostic::Error; 296 break; 297 case diag::MAP_ERROR: 298 Result = Diagnostic::Error; 299 break; 300 case diag::MAP_FATAL: 301 Result = Diagnostic::Fatal; 302 break; 303 case diag::MAP_WARNING: 304 // If warnings are globally mapped to ignore or error, do it. 305 if (IgnoreAllWarnings) 306 return Diagnostic::Ignored; 307 308 Result = Diagnostic::Warning; 309 310 // If this is an extension diagnostic and we're in -pedantic-error mode, and 311 // if the user didn't explicitly map it, upgrade to an error. 312 if (ExtBehavior == Ext_Error && 313 (MappingInfo & 8) == 0 && 314 isBuiltinExtensionDiag(DiagID)) 315 Result = Diagnostic::Error; 316 317 if (WarningsAsErrors) 318 Result = Diagnostic::Error; 319 break; 320 321 case diag::MAP_WARNING_NO_WERROR: 322 // Diagnostics specified with -Wno-error=foo should be set to warnings, but 323 // not be adjusted by -Werror or -pedantic-errors. 324 Result = Diagnostic::Warning; 325 326 // If warnings are globally mapped to ignore or error, do it. 327 if (IgnoreAllWarnings) 328 return Diagnostic::Ignored; 329 330 break; 331 } 332 333 // Okay, we're about to return this as a "diagnostic to emit" one last check: 334 // if this is any sort of extension warning, and if we're in an __extension__ 335 // block, silence it. 336 if (AllExtensionsSilenced && isBuiltinExtensionDiag(DiagID)) 337 return Diagnostic::Ignored; 338 339 return Result; 340} 341 342struct WarningOption { 343 const char *Name; 344 const short *Members; 345 const char *SubGroups; 346}; 347 348#define GET_DIAG_ARRAYS 349#include "clang/Basic/DiagnosticGroups.inc" 350#undef GET_DIAG_ARRAYS 351 352// Second the table of options, sorted by name for fast binary lookup. 353static const WarningOption OptionTable[] = { 354#define GET_DIAG_TABLE 355#include "clang/Basic/DiagnosticGroups.inc" 356#undef GET_DIAG_TABLE 357}; 358static const size_t OptionTableSize = 359sizeof(OptionTable) / sizeof(OptionTable[0]); 360 361static bool WarningOptionCompare(const WarningOption &LHS, 362 const WarningOption &RHS) { 363 return strcmp(LHS.Name, RHS.Name) < 0; 364} 365 366static void MapGroupMembers(const WarningOption *Group, diag::Mapping Mapping, 367 Diagnostic &Diags) { 368 // Option exists, poke all the members of its diagnostic set. 369 if (const short *Member = Group->Members) { 370 for (; *Member != -1; ++Member) 371 Diags.setDiagnosticMapping(*Member, Mapping); 372 } 373 374 // Enable/disable all subgroups along with this one. 375 if (const char *SubGroups = Group->SubGroups) { 376 for (; *SubGroups != (char)-1; ++SubGroups) 377 MapGroupMembers(&OptionTable[(unsigned char)*SubGroups], Mapping, Diags); 378 } 379} 380 381/// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g. 382/// "unknown-pragmas" to have the specified mapping. This returns true and 383/// ignores the request if "Group" was unknown, false otherwise. 384bool Diagnostic::setDiagnosticGroupMapping(const char *Group, 385 diag::Mapping Map) { 386 387 WarningOption Key = { Group, 0, 0 }; 388 const WarningOption *Found = 389 std::lower_bound(OptionTable, OptionTable + OptionTableSize, Key, 390 WarningOptionCompare); 391 if (Found == OptionTable + OptionTableSize || 392 strcmp(Found->Name, Group) != 0) 393 return true; // Option not found. 394 395 MapGroupMembers(Found, Map, *this); 396 return false; 397} 398 399 400/// ProcessDiag - This is the method used to report a diagnostic that is 401/// finally fully formed. 402void Diagnostic::ProcessDiag() { 403 DiagnosticInfo Info(this); 404 405 // Figure out the diagnostic level of this message. 406 Diagnostic::Level DiagLevel; 407 unsigned DiagID = Info.getID(); 408 409 // ShouldEmitInSystemHeader - True if this diagnostic should be produced even 410 // in a system header. 411 bool ShouldEmitInSystemHeader; 412 413 if (DiagID >= diag::DIAG_UPPER_LIMIT) { 414 // Handle custom diagnostics, which cannot be mapped. 415 DiagLevel = CustomDiagInfo->getLevel(DiagID); 416 417 // Custom diagnostics always are emitted in system headers. 418 ShouldEmitInSystemHeader = true; 419 } else { 420 // Get the class of the diagnostic. If this is a NOTE, map it onto whatever 421 // the diagnostic level was for the previous diagnostic so that it is 422 // filtered the same as the previous diagnostic. 423 unsigned DiagClass = getBuiltinDiagClass(DiagID); 424 if (DiagClass == CLASS_NOTE) { 425 DiagLevel = Diagnostic::Note; 426 ShouldEmitInSystemHeader = false; // extra consideration is needed 427 } else { 428 // If this is not an error and we are in a system header, we ignore it. 429 // Check the original Diag ID here, because we also want to ignore 430 // extensions and warnings in -Werror and -pedantic-errors modes, which 431 // *map* warnings/extensions to errors. 432 ShouldEmitInSystemHeader = DiagClass == CLASS_ERROR; 433 434 DiagLevel = getDiagnosticLevel(DiagID, DiagClass); 435 } 436 } 437 438 if (DiagLevel != Diagnostic::Note) { 439 // Record that a fatal error occurred only when we see a second 440 // non-note diagnostic. This allows notes to be attached to the 441 // fatal error, but suppresses any diagnostics that follow those 442 // notes. 443 if (LastDiagLevel == Diagnostic::Fatal) 444 FatalErrorOccurred = true; 445 446 LastDiagLevel = DiagLevel; 447 } 448 449 // If a fatal error has already been emitted, silence all subsequent 450 // diagnostics. 451 if (FatalErrorOccurred) 452 return; 453 454 // If the client doesn't care about this message, don't issue it. If this is 455 // a note and the last real diagnostic was ignored, ignore it too. 456 if (DiagLevel == Diagnostic::Ignored || 457 (DiagLevel == Diagnostic::Note && LastDiagLevel == Diagnostic::Ignored)) 458 return; 459 460 // If this diagnostic is in a system header and is not a clang error, suppress 461 // it. 462 if (SuppressSystemWarnings && !ShouldEmitInSystemHeader && 463 Info.getLocation().isValid() && 464 Info.getLocation().getSpellingLoc().isInSystemHeader() && 465 (DiagLevel != Diagnostic::Note || LastDiagLevel == Diagnostic::Ignored)) { 466 LastDiagLevel = Diagnostic::Ignored; 467 return; 468 } 469 470 if (DiagLevel >= Diagnostic::Error) { 471 ErrorOccurred = true; 472 ++NumErrors; 473 } 474 475 // Finally, report it. 476 Client->HandleDiagnostic(DiagLevel, Info); 477 if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics; 478 479 CurDiagID = ~0U; 480} 481 482 483DiagnosticClient::~DiagnosticClient() {} 484 485 486/// ModifierIs - Return true if the specified modifier matches specified string. 487template <std::size_t StrLen> 488static bool ModifierIs(const char *Modifier, unsigned ModifierLen, 489 const char (&Str)[StrLen]) { 490 return StrLen-1 == ModifierLen && !memcmp(Modifier, Str, StrLen-1); 491} 492 493/// HandleSelectModifier - Handle the integer 'select' modifier. This is used 494/// like this: %select{foo|bar|baz}2. This means that the integer argument 495/// "%2" has a value from 0-2. If the value is 0, the diagnostic prints 'foo'. 496/// If the value is 1, it prints 'bar'. If it has the value 2, it prints 'baz'. 497/// This is very useful for certain classes of variant diagnostics. 498static void HandleSelectModifier(unsigned ValNo, 499 const char *Argument, unsigned ArgumentLen, 500 llvm::SmallVectorImpl<char> &OutStr) { 501 const char *ArgumentEnd = Argument+ArgumentLen; 502 503 // Skip over 'ValNo' |'s. 504 while (ValNo) { 505 const char *NextVal = std::find(Argument, ArgumentEnd, '|'); 506 assert(NextVal != ArgumentEnd && "Value for integer select modifier was" 507 " larger than the number of options in the diagnostic string!"); 508 Argument = NextVal+1; // Skip this string. 509 --ValNo; 510 } 511 512 // Get the end of the value. This is either the } or the |. 513 const char *EndPtr = std::find(Argument, ArgumentEnd, '|'); 514 // Add the value to the output string. 515 OutStr.append(Argument, EndPtr); 516} 517 518/// HandleIntegerSModifier - Handle the integer 's' modifier. This adds the 519/// letter 's' to the string if the value is not 1. This is used in cases like 520/// this: "you idiot, you have %4 parameter%s4!". 521static void HandleIntegerSModifier(unsigned ValNo, 522 llvm::SmallVectorImpl<char> &OutStr) { 523 if (ValNo != 1) 524 OutStr.push_back('s'); 525} 526 527 528/// PluralNumber - Parse an unsigned integer and advance Start. 529static unsigned PluralNumber(const char *&Start, const char *End) { 530 // Programming 101: Parse a decimal number :-) 531 unsigned Val = 0; 532 while (Start != End && *Start >= '0' && *Start <= '9') { 533 Val *= 10; 534 Val += *Start - '0'; 535 ++Start; 536 } 537 return Val; 538} 539 540/// TestPluralRange - Test if Val is in the parsed range. Modifies Start. 541static bool TestPluralRange(unsigned Val, const char *&Start, const char *End) { 542 if (*Start != '[') { 543 unsigned Ref = PluralNumber(Start, End); 544 return Ref == Val; 545 } 546 547 ++Start; 548 unsigned Low = PluralNumber(Start, End); 549 assert(*Start == ',' && "Bad plural expression syntax: expected ,"); 550 ++Start; 551 unsigned High = PluralNumber(Start, End); 552 assert(*Start == ']' && "Bad plural expression syntax: expected )"); 553 ++Start; 554 return Low <= Val && Val <= High; 555} 556 557/// EvalPluralExpr - Actual expression evaluator for HandlePluralModifier. 558static bool EvalPluralExpr(unsigned ValNo, const char *Start, const char *End) { 559 // Empty condition? 560 if (*Start == ':') 561 return true; 562 563 while (1) { 564 char C = *Start; 565 if (C == '%') { 566 // Modulo expression 567 ++Start; 568 unsigned Arg = PluralNumber(Start, End); 569 assert(*Start == '=' && "Bad plural expression syntax: expected ="); 570 ++Start; 571 unsigned ValMod = ValNo % Arg; 572 if (TestPluralRange(ValMod, Start, End)) 573 return true; 574 } else { 575 assert((C == '[' || (C >= '0' && C <= '9')) && 576 "Bad plural expression syntax: unexpected character"); 577 // Range expression 578 if (TestPluralRange(ValNo, Start, End)) 579 return true; 580 } 581 582 // Scan for next or-expr part. 583 Start = std::find(Start, End, ','); 584 if(Start == End) 585 break; 586 ++Start; 587 } 588 return false; 589} 590 591/// HandlePluralModifier - Handle the integer 'plural' modifier. This is used 592/// for complex plural forms, or in languages where all plurals are complex. 593/// The syntax is: %plural{cond1:form1|cond2:form2|:form3}, where condn are 594/// conditions that are tested in order, the form corresponding to the first 595/// that applies being emitted. The empty condition is always true, making the 596/// last form a default case. 597/// Conditions are simple boolean expressions, where n is the number argument. 598/// Here are the rules. 599/// condition := expression | empty 600/// empty := -> always true 601/// expression := numeric [',' expression] -> logical or 602/// numeric := range -> true if n in range 603/// | '%' number '=' range -> true if n % number in range 604/// range := number 605/// | '[' number ',' number ']' -> ranges are inclusive both ends 606/// 607/// Here are some examples from the GNU gettext manual written in this form: 608/// English: 609/// {1:form0|:form1} 610/// Latvian: 611/// {0:form2|%100=11,%10=0,%10=[2,9]:form1|:form0} 612/// Gaeilge: 613/// {1:form0|2:form1|:form2} 614/// Romanian: 615/// {1:form0|0,%100=[1,19]:form1|:form2} 616/// Lithuanian: 617/// {%10=0,%100=[10,19]:form2|%10=1:form0|:form1} 618/// Russian (requires repeated form): 619/// {%100=[11,14]:form2|%10=1:form0|%10=[2,4]:form1|:form2} 620/// Slovak 621/// {1:form0|[2,4]:form1|:form2} 622/// Polish (requires repeated form): 623/// {1:form0|%100=[10,20]:form2|%10=[2,4]:form1|:form2} 624static void HandlePluralModifier(unsigned ValNo, 625 const char *Argument, unsigned ArgumentLen, 626 llvm::SmallVectorImpl<char> &OutStr) { 627 const char *ArgumentEnd = Argument + ArgumentLen; 628 while (1) { 629 assert(Argument < ArgumentEnd && "Plural expression didn't match."); 630 const char *ExprEnd = Argument; 631 while (*ExprEnd != ':') { 632 assert(ExprEnd != ArgumentEnd && "Plural missing expression end"); 633 ++ExprEnd; 634 } 635 if (EvalPluralExpr(ValNo, Argument, ExprEnd)) { 636 Argument = ExprEnd + 1; 637 ExprEnd = std::find(Argument, ArgumentEnd, '|'); 638 OutStr.append(Argument, ExprEnd); 639 return; 640 } 641 Argument = std::find(Argument, ArgumentEnd - 1, '|') + 1; 642 } 643} 644 645 646/// FormatDiagnostic - Format this diagnostic into a string, substituting the 647/// formal arguments into the %0 slots. The result is appended onto the Str 648/// array. 649void DiagnosticInfo:: 650FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const { 651 const char *DiagStr = getDiags()->getDescription(getID()); 652 const char *DiagEnd = DiagStr+strlen(DiagStr); 653 654 while (DiagStr != DiagEnd) { 655 if (DiagStr[0] != '%') { 656 // Append non-%0 substrings to Str if we have one. 657 const char *StrEnd = std::find(DiagStr, DiagEnd, '%'); 658 OutStr.append(DiagStr, StrEnd); 659 DiagStr = StrEnd; 660 continue; 661 } else if (DiagStr[1] == '%') { 662 OutStr.push_back('%'); // %% -> %. 663 DiagStr += 2; 664 continue; 665 } 666 667 // Skip the %. 668 ++DiagStr; 669 670 // This must be a placeholder for a diagnostic argument. The format for a 671 // placeholder is one of "%0", "%modifier0", or "%modifier{arguments}0". 672 // The digit is a number from 0-9 indicating which argument this comes from. 673 // The modifier is a string of digits from the set [-a-z]+, arguments is a 674 // brace enclosed string. 675 const char *Modifier = 0, *Argument = 0; 676 unsigned ModifierLen = 0, ArgumentLen = 0; 677 678 // Check to see if we have a modifier. If so eat it. 679 if (!isdigit(DiagStr[0])) { 680 Modifier = DiagStr; 681 while (DiagStr[0] == '-' || 682 (DiagStr[0] >= 'a' && DiagStr[0] <= 'z')) 683 ++DiagStr; 684 ModifierLen = DiagStr-Modifier; 685 686 // If we have an argument, get it next. 687 if (DiagStr[0] == '{') { 688 ++DiagStr; // Skip {. 689 Argument = DiagStr; 690 691 for (; DiagStr[0] != '}'; ++DiagStr) 692 assert(DiagStr[0] && "Mismatched {}'s in diagnostic string!"); 693 ArgumentLen = DiagStr-Argument; 694 ++DiagStr; // Skip }. 695 } 696 } 697 698 assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic"); 699 unsigned ArgNo = *DiagStr++ - '0'; 700 701 switch (getArgKind(ArgNo)) { 702 // ---- STRINGS ---- 703 case Diagnostic::ak_std_string: { 704 const std::string &S = getArgStdStr(ArgNo); 705 assert(ModifierLen == 0 && "No modifiers for strings yet"); 706 OutStr.append(S.begin(), S.end()); 707 break; 708 } 709 case Diagnostic::ak_c_string: { 710 const char *S = getArgCStr(ArgNo); 711 assert(ModifierLen == 0 && "No modifiers for strings yet"); 712 713 // Don't crash if get passed a null pointer by accident. 714 if (!S) 715 S = "(null)"; 716 717 OutStr.append(S, S + strlen(S)); 718 break; 719 } 720 // ---- INTEGERS ---- 721 case Diagnostic::ak_sint: { 722 int Val = getArgSInt(ArgNo); 723 724 if (ModifierIs(Modifier, ModifierLen, "select")) { 725 HandleSelectModifier((unsigned)Val, Argument, ArgumentLen, OutStr); 726 } else if (ModifierIs(Modifier, ModifierLen, "s")) { 727 HandleIntegerSModifier(Val, OutStr); 728 } else if (ModifierIs(Modifier, ModifierLen, "plural")) { 729 HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr); 730 } else { 731 assert(ModifierLen == 0 && "Unknown integer modifier"); 732 // FIXME: Optimize 733 std::string S = llvm::itostr(Val); 734 OutStr.append(S.begin(), S.end()); 735 } 736 break; 737 } 738 case Diagnostic::ak_uint: { 739 unsigned Val = getArgUInt(ArgNo); 740 741 if (ModifierIs(Modifier, ModifierLen, "select")) { 742 HandleSelectModifier(Val, Argument, ArgumentLen, OutStr); 743 } else if (ModifierIs(Modifier, ModifierLen, "s")) { 744 HandleIntegerSModifier(Val, OutStr); 745 } else if (ModifierIs(Modifier, ModifierLen, "plural")) { 746 HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr); 747 } else { 748 assert(ModifierLen == 0 && "Unknown integer modifier"); 749 750 // FIXME: Optimize 751 std::string S = llvm::utostr_32(Val); 752 OutStr.append(S.begin(), S.end()); 753 } 754 break; 755 } 756 // ---- NAMES and TYPES ---- 757 case Diagnostic::ak_identifierinfo: { 758 const IdentifierInfo *II = getArgIdentifier(ArgNo); 759 assert(ModifierLen == 0 && "No modifiers for strings yet"); 760 761 // Don't crash if get passed a null pointer by accident. 762 if (!II) { 763 const char *S = "(null)"; 764 OutStr.append(S, S + strlen(S)); 765 continue; 766 } 767 768 OutStr.push_back('\''); 769 OutStr.append(II->getName(), II->getName() + II->getLength()); 770 OutStr.push_back('\''); 771 break; 772 } 773 case Diagnostic::ak_qualtype: 774 case Diagnostic::ak_declarationname: 775 case Diagnostic::ak_nameddecl: 776 getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo), 777 Modifier, ModifierLen, 778 Argument, ArgumentLen, OutStr); 779 break; 780 } 781 } 782} 783 784/// IncludeInDiagnosticCounts - This method (whose default implementation 785/// returns true) indicates whether the diagnostics handled by this 786/// DiagnosticClient should be included in the number of diagnostics 787/// reported by Diagnostic. 788bool DiagnosticClient::IncludeInDiagnosticCounts() const { return true; } 789