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