1 //== PrintfFormatString.cpp - Analysis of printf format strings --*- 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 // Handling of format string in printf and friends. The structure of format 11 // strings for fprintf() are described in C99 7.19.6.1. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/Analysis/Analyses/FormatString.h" 16 #include "FormatStringParsing.h" 17 #include "clang/Basic/TargetInfo.h" 18 19 using clang::analyze_format_string::ArgType; 20 using clang::analyze_format_string::FormatStringHandler; 21 using clang::analyze_format_string::LengthModifier; 22 using clang::analyze_format_string::OptionalAmount; 23 using clang::analyze_format_string::ConversionSpecifier; 24 using clang::analyze_printf::PrintfSpecifier; 25 26 using namespace clang; 27 28 typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier> 29 PrintfSpecifierResult; 30 31 //===----------------------------------------------------------------------===// 32 // Methods for parsing format strings. 33 //===----------------------------------------------------------------------===// 34 35 using analyze_format_string::ParseNonPositionAmount; 36 37 static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS, 38 const char *Start, const char *&Beg, const char *E, 39 unsigned *argIndex) { 40 if (argIndex) { 41 FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex)); 42 } else { 43 const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 44 analyze_format_string::PrecisionPos); 45 if (Amt.isInvalid()) 46 return true; 47 FS.setPrecision(Amt); 48 } 49 return false; 50 } 51 52 static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, 53 const char *&Beg, 54 const char *E, 55 unsigned &argIndex, 56 const LangOptions &LO, 57 const TargetInfo &Target) { 58 59 using namespace clang::analyze_format_string; 60 using namespace clang::analyze_printf; 61 62 const char *I = Beg; 63 const char *Start = nullptr; 64 UpdateOnReturn <const char*> UpdateBeg(Beg, I); 65 66 // Look for a '%' character that indicates the start of a format specifier. 67 for ( ; I != E ; ++I) { 68 char c = *I; 69 if (c == '\0') { 70 // Detect spurious null characters, which are likely errors. 71 H.HandleNullChar(I); 72 return true; 73 } 74 if (c == '%') { 75 Start = I++; // Record the start of the format specifier. 76 break; 77 } 78 } 79 80 // No format specifier found? 81 if (!Start) 82 return false; 83 84 if (I == E) { 85 // No more characters left? 86 H.HandleIncompleteSpecifier(Start, E - Start); 87 return true; 88 } 89 90 PrintfSpecifier FS; 91 if (ParseArgPosition(H, FS, Start, I, E)) 92 return true; 93 94 if (I == E) { 95 // No more characters left? 96 H.HandleIncompleteSpecifier(Start, E - Start); 97 return true; 98 } 99 100 // Look for flags (if any). 101 bool hasMore = true; 102 for ( ; I != E; ++I) { 103 switch (*I) { 104 default: hasMore = false; break; 105 case '\'': 106 // FIXME: POSIX specific. Always accept? 107 FS.setHasThousandsGrouping(I); 108 break; 109 case '-': FS.setIsLeftJustified(I); break; 110 case '+': FS.setHasPlusPrefix(I); break; 111 case ' ': FS.setHasSpacePrefix(I); break; 112 case '#': FS.setHasAlternativeForm(I); break; 113 case '0': FS.setHasLeadingZeros(I); break; 114 } 115 if (!hasMore) 116 break; 117 } 118 119 if (I == E) { 120 // No more characters left? 121 H.HandleIncompleteSpecifier(Start, E - Start); 122 return true; 123 } 124 125 // Look for the field width (if any). 126 if (ParseFieldWidth(H, FS, Start, I, E, 127 FS.usesPositionalArg() ? nullptr : &argIndex)) 128 return true; 129 130 if (I == E) { 131 // No more characters left? 132 H.HandleIncompleteSpecifier(Start, E - Start); 133 return true; 134 } 135 136 // Look for the precision (if any). 137 if (*I == '.') { 138 ++I; 139 if (I == E) { 140 H.HandleIncompleteSpecifier(Start, E - Start); 141 return true; 142 } 143 144 if (ParsePrecision(H, FS, Start, I, E, 145 FS.usesPositionalArg() ? nullptr : &argIndex)) 146 return true; 147 148 if (I == E) { 149 // No more characters left? 150 H.HandleIncompleteSpecifier(Start, E - Start); 151 return true; 152 } 153 } 154 155 // Look for the length modifier. 156 if (ParseLengthModifier(FS, I, E, LO) && I == E) { 157 // No more characters left? 158 H.HandleIncompleteSpecifier(Start, E - Start); 159 return true; 160 } 161 162 if (*I == '\0') { 163 // Detect spurious null characters, which are likely errors. 164 H.HandleNullChar(I); 165 return true; 166 } 167 168 // Finally, look for the conversion specifier. 169 const char *conversionPosition = I++; 170 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 171 switch (*conversionPosition) { 172 default: 173 break; 174 // C99: 7.19.6.1 (section 8). 175 case '%': k = ConversionSpecifier::PercentArg; break; 176 case 'A': k = ConversionSpecifier::AArg; break; 177 case 'E': k = ConversionSpecifier::EArg; break; 178 case 'F': k = ConversionSpecifier::FArg; break; 179 case 'G': k = ConversionSpecifier::GArg; break; 180 case 'X': k = ConversionSpecifier::XArg; break; 181 case 'a': k = ConversionSpecifier::aArg; break; 182 case 'c': k = ConversionSpecifier::cArg; break; 183 case 'd': k = ConversionSpecifier::dArg; break; 184 case 'e': k = ConversionSpecifier::eArg; break; 185 case 'f': k = ConversionSpecifier::fArg; break; 186 case 'g': k = ConversionSpecifier::gArg; break; 187 case 'i': k = ConversionSpecifier::iArg; break; 188 case 'n': k = ConversionSpecifier::nArg; break; 189 case 'o': k = ConversionSpecifier::oArg; break; 190 case 'p': k = ConversionSpecifier::pArg; break; 191 case 's': k = ConversionSpecifier::sArg; break; 192 case 'u': k = ConversionSpecifier::uArg; break; 193 case 'x': k = ConversionSpecifier::xArg; break; 194 // POSIX specific. 195 case 'C': k = ConversionSpecifier::CArg; break; 196 case 'S': k = ConversionSpecifier::SArg; break; 197 // Objective-C. 198 case '@': k = ConversionSpecifier::ObjCObjArg; break; 199 // Glibc specific. 200 case 'm': k = ConversionSpecifier::PrintErrno; break; 201 // Apple-specific 202 case 'D': 203 if (Target.getTriple().isOSDarwin()) 204 k = ConversionSpecifier::DArg; 205 break; 206 case 'O': 207 if (Target.getTriple().isOSDarwin()) 208 k = ConversionSpecifier::OArg; 209 break; 210 case 'U': 211 if (Target.getTriple().isOSDarwin()) 212 k = ConversionSpecifier::UArg; 213 break; 214 } 215 PrintfConversionSpecifier CS(conversionPosition, k); 216 FS.setConversionSpecifier(CS); 217 if (CS.consumesDataArgument() && !FS.usesPositionalArg()) 218 FS.setArgIndex(argIndex++); 219 220 if (k == ConversionSpecifier::InvalidSpecifier) { 221 // Assume the conversion takes one argument. 222 return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start); 223 } 224 return PrintfSpecifierResult(Start, FS); 225 } 226 227 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H, 228 const char *I, 229 const char *E, 230 const LangOptions &LO, 231 const TargetInfo &Target) { 232 233 unsigned argIndex = 0; 234 235 // Keep looking for a format specifier until we have exhausted the string. 236 while (I != E) { 237 const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 238 LO, Target); 239 // Did a fail-stop error of any kind occur when parsing the specifier? 240 // If so, don't do any more processing. 241 if (FSR.shouldStop()) 242 return true; 243 // Did we exhaust the string or encounter an error that 244 // we can recover from? 245 if (!FSR.hasValue()) 246 continue; 247 // We have a format specifier. Pass it to the callback. 248 if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(), 249 I - FSR.getStart())) 250 return true; 251 } 252 assert(I == E && "Format string not exhausted"); 253 return false; 254 } 255 256 //===----------------------------------------------------------------------===// 257 // Methods on PrintfSpecifier. 258 //===----------------------------------------------------------------------===// 259 260 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx, 261 bool IsObjCLiteral) const { 262 const PrintfConversionSpecifier &CS = getConversionSpecifier(); 263 264 if (!CS.consumesDataArgument()) 265 return ArgType::Invalid(); 266 267 if (CS.getKind() == ConversionSpecifier::cArg) 268 switch (LM.getKind()) { 269 case LengthModifier::None: return Ctx.IntTy; 270 case LengthModifier::AsLong: 271 return ArgType(ArgType::WIntTy, "wint_t"); 272 default: 273 return ArgType::Invalid(); 274 } 275 276 if (CS.isIntArg()) 277 switch (LM.getKind()) { 278 case LengthModifier::AsLongDouble: 279 // GNU extension. 280 return Ctx.LongLongTy; 281 case LengthModifier::None: 282 return Ctx.IntTy; 283 case LengthModifier::AsInt32: 284 return ArgType(Ctx.IntTy, "__int32"); 285 case LengthModifier::AsChar: return ArgType::AnyCharTy; 286 case LengthModifier::AsShort: return Ctx.ShortTy; 287 case LengthModifier::AsLong: return Ctx.LongTy; 288 case LengthModifier::AsLongLong: 289 case LengthModifier::AsQuad: 290 return Ctx.LongLongTy; 291 case LengthModifier::AsInt64: 292 return ArgType(Ctx.LongLongTy, "__int64"); 293 case LengthModifier::AsIntMax: 294 return ArgType(Ctx.getIntMaxType(), "intmax_t"); 295 case LengthModifier::AsSizeT: 296 // FIXME: How to get the corresponding signed version of size_t? 297 return ArgType(); 298 case LengthModifier::AsInt3264: 299 return Ctx.getTargetInfo().getTriple().isArch64Bit() 300 ? ArgType(Ctx.LongLongTy, "__int64") 301 : ArgType(Ctx.IntTy, "__int32"); 302 case LengthModifier::AsPtrDiff: 303 return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"); 304 case LengthModifier::AsAllocate: 305 case LengthModifier::AsMAllocate: 306 return ArgType::Invalid(); 307 } 308 309 if (CS.isUIntArg()) 310 switch (LM.getKind()) { 311 case LengthModifier::AsLongDouble: 312 // GNU extension. 313 return Ctx.UnsignedLongLongTy; 314 case LengthModifier::None: 315 return Ctx.UnsignedIntTy; 316 case LengthModifier::AsInt32: 317 return ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); 318 case LengthModifier::AsChar: return Ctx.UnsignedCharTy; 319 case LengthModifier::AsShort: return Ctx.UnsignedShortTy; 320 case LengthModifier::AsLong: return Ctx.UnsignedLongTy; 321 case LengthModifier::AsLongLong: 322 case LengthModifier::AsQuad: 323 return Ctx.UnsignedLongLongTy; 324 case LengthModifier::AsInt64: 325 return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64"); 326 case LengthModifier::AsIntMax: 327 return ArgType(Ctx.getUIntMaxType(), "uintmax_t"); 328 case LengthModifier::AsSizeT: 329 return ArgType(Ctx.getSizeType(), "size_t"); 330 case LengthModifier::AsInt3264: 331 return Ctx.getTargetInfo().getTriple().isArch64Bit() 332 ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64") 333 : ArgType(Ctx.UnsignedIntTy, "unsigned __int32"); 334 case LengthModifier::AsPtrDiff: 335 // FIXME: How to get the corresponding unsigned 336 // version of ptrdiff_t? 337 return ArgType(); 338 case LengthModifier::AsAllocate: 339 case LengthModifier::AsMAllocate: 340 return ArgType::Invalid(); 341 } 342 343 if (CS.isDoubleArg()) { 344 if (LM.getKind() == LengthModifier::AsLongDouble) 345 return Ctx.LongDoubleTy; 346 return Ctx.DoubleTy; 347 } 348 349 if (CS.getKind() == ConversionSpecifier::nArg) { 350 switch (LM.getKind()) { 351 case LengthModifier::None: 352 return ArgType::PtrTo(Ctx.IntTy); 353 case LengthModifier::AsChar: 354 return ArgType::PtrTo(Ctx.SignedCharTy); 355 case LengthModifier::AsShort: 356 return ArgType::PtrTo(Ctx.ShortTy); 357 case LengthModifier::AsLong: 358 return ArgType::PtrTo(Ctx.LongTy); 359 case LengthModifier::AsLongLong: 360 case LengthModifier::AsQuad: 361 return ArgType::PtrTo(Ctx.LongLongTy); 362 case LengthModifier::AsIntMax: 363 return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); 364 case LengthModifier::AsSizeT: 365 return ArgType(); // FIXME: ssize_t 366 case LengthModifier::AsPtrDiff: 367 return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); 368 case LengthModifier::AsLongDouble: 369 return ArgType(); // FIXME: Is this a known extension? 370 case LengthModifier::AsAllocate: 371 case LengthModifier::AsMAllocate: 372 case LengthModifier::AsInt32: 373 case LengthModifier::AsInt3264: 374 case LengthModifier::AsInt64: 375 return ArgType::Invalid(); 376 } 377 } 378 379 switch (CS.getKind()) { 380 case ConversionSpecifier::sArg: 381 if (LM.getKind() == LengthModifier::AsWideChar) { 382 if (IsObjCLiteral) 383 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), 384 "const unichar *"); 385 return ArgType(ArgType::WCStrTy, "wchar_t *"); 386 } 387 return ArgType::CStrTy; 388 case ConversionSpecifier::SArg: 389 if (IsObjCLiteral) 390 return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()), 391 "const unichar *"); 392 return ArgType(ArgType::WCStrTy, "wchar_t *"); 393 case ConversionSpecifier::CArg: 394 if (IsObjCLiteral) 395 return ArgType(Ctx.UnsignedShortTy, "unichar"); 396 return ArgType(Ctx.WideCharTy, "wchar_t"); 397 case ConversionSpecifier::pArg: 398 return ArgType::CPointerTy; 399 case ConversionSpecifier::ObjCObjArg: 400 return ArgType::ObjCPointerTy; 401 default: 402 break; 403 } 404 405 // FIXME: Handle other cases. 406 return ArgType(); 407 } 408 409 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, 410 ASTContext &Ctx, bool IsObjCLiteral) { 411 // %n is different from other conversion specifiers; don't try to fix it. 412 if (CS.getKind() == ConversionSpecifier::nArg) 413 return false; 414 415 // Handle Objective-C objects first. Note that while the '%@' specifier will 416 // not warn for structure pointer or void pointer arguments (because that's 417 // how CoreFoundation objects are implemented), we only show a fixit for '%@' 418 // if we know it's an object (block, id, class, or __attribute__((NSObject))). 419 if (QT->isObjCRetainableType()) { 420 if (!IsObjCLiteral) 421 return false; 422 423 CS.setKind(ConversionSpecifier::ObjCObjArg); 424 425 // Disable irrelevant flags 426 HasThousandsGrouping = false; 427 HasPlusPrefix = false; 428 HasSpacePrefix = false; 429 HasAlternativeForm = false; 430 HasLeadingZeroes = false; 431 Precision.setHowSpecified(OptionalAmount::NotSpecified); 432 LM.setKind(LengthModifier::None); 433 434 return true; 435 } 436 437 // Handle strings next (char *, wchar_t *) 438 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { 439 CS.setKind(ConversionSpecifier::sArg); 440 441 // Disable irrelevant flags 442 HasAlternativeForm = 0; 443 HasLeadingZeroes = 0; 444 445 // Set the long length modifier for wide characters 446 if (QT->getPointeeType()->isWideCharType()) 447 LM.setKind(LengthModifier::AsWideChar); 448 else 449 LM.setKind(LengthModifier::None); 450 451 return true; 452 } 453 454 // If it's an enum, get its underlying type. 455 if (const EnumType *ETy = QT->getAs<EnumType>()) 456 QT = ETy->getDecl()->getIntegerType(); 457 458 // We can only work with builtin types. 459 const BuiltinType *BT = QT->getAs<BuiltinType>(); 460 if (!BT) 461 return false; 462 463 // Set length modifier 464 switch (BT->getKind()) { 465 case BuiltinType::Bool: 466 case BuiltinType::WChar_U: 467 case BuiltinType::WChar_S: 468 case BuiltinType::Char16: 469 case BuiltinType::Char32: 470 case BuiltinType::UInt128: 471 case BuiltinType::Int128: 472 case BuiltinType::Half: 473 // Various types which are non-trivial to correct. 474 return false; 475 476 #define SIGNED_TYPE(Id, SingletonId) 477 #define UNSIGNED_TYPE(Id, SingletonId) 478 #define FLOATING_TYPE(Id, SingletonId) 479 #define BUILTIN_TYPE(Id, SingletonId) \ 480 case BuiltinType::Id: 481 #include "clang/AST/BuiltinTypes.def" 482 // Misc other stuff which doesn't make sense here. 483 return false; 484 485 case BuiltinType::UInt: 486 case BuiltinType::Int: 487 case BuiltinType::Float: 488 case BuiltinType::Double: 489 LM.setKind(LengthModifier::None); 490 break; 491 492 case BuiltinType::Char_U: 493 case BuiltinType::UChar: 494 case BuiltinType::Char_S: 495 case BuiltinType::SChar: 496 LM.setKind(LengthModifier::AsChar); 497 break; 498 499 case BuiltinType::Short: 500 case BuiltinType::UShort: 501 LM.setKind(LengthModifier::AsShort); 502 break; 503 504 case BuiltinType::Long: 505 case BuiltinType::ULong: 506 LM.setKind(LengthModifier::AsLong); 507 break; 508 509 case BuiltinType::LongLong: 510 case BuiltinType::ULongLong: 511 LM.setKind(LengthModifier::AsLongLong); 512 break; 513 514 case BuiltinType::LongDouble: 515 LM.setKind(LengthModifier::AsLongDouble); 516 break; 517 } 518 519 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. 520 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11)) 521 namedTypeToLengthModifier(QT, LM); 522 523 // If fixing the length modifier was enough, we might be done. 524 if (hasValidLengthModifier(Ctx.getTargetInfo())) { 525 // If we're going to offer a fix anyway, make sure the sign matches. 526 switch (CS.getKind()) { 527 case ConversionSpecifier::uArg: 528 case ConversionSpecifier::UArg: 529 if (QT->isSignedIntegerType()) 530 CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg); 531 break; 532 case ConversionSpecifier::dArg: 533 case ConversionSpecifier::DArg: 534 case ConversionSpecifier::iArg: 535 if (QT->isUnsignedIntegerType() && !HasPlusPrefix) 536 CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg); 537 break; 538 default: 539 // Other specifiers do not have signed/unsigned variants. 540 break; 541 } 542 543 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral); 544 if (ATR.isValid() && ATR.matchesType(Ctx, QT)) 545 return true; 546 } 547 548 // Set conversion specifier and disable any flags which do not apply to it. 549 // Let typedefs to char fall through to int, as %c is silly for uint8_t. 550 if (!isa<TypedefType>(QT) && QT->isCharType()) { 551 CS.setKind(ConversionSpecifier::cArg); 552 LM.setKind(LengthModifier::None); 553 Precision.setHowSpecified(OptionalAmount::NotSpecified); 554 HasAlternativeForm = 0; 555 HasLeadingZeroes = 0; 556 HasPlusPrefix = 0; 557 } 558 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType 559 else if (QT->isRealFloatingType()) { 560 CS.setKind(ConversionSpecifier::fArg); 561 } 562 else if (QT->isSignedIntegerType()) { 563 CS.setKind(ConversionSpecifier::dArg); 564 HasAlternativeForm = 0; 565 } 566 else if (QT->isUnsignedIntegerType()) { 567 CS.setKind(ConversionSpecifier::uArg); 568 HasAlternativeForm = 0; 569 HasPlusPrefix = 0; 570 } else { 571 llvm_unreachable("Unexpected type"); 572 } 573 574 return true; 575 } 576 577 void PrintfSpecifier::toString(raw_ostream &os) const { 578 // Whilst some features have no defined order, we are using the order 579 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1) 580 os << "%"; 581 582 // Positional args 583 if (usesPositionalArg()) { 584 os << getPositionalArgIndex() << "$"; 585 } 586 587 // Conversion flags 588 if (IsLeftJustified) os << "-"; 589 if (HasPlusPrefix) os << "+"; 590 if (HasSpacePrefix) os << " "; 591 if (HasAlternativeForm) os << "#"; 592 if (HasLeadingZeroes) os << "0"; 593 594 // Minimum field width 595 FieldWidth.toString(os); 596 // Precision 597 Precision.toString(os); 598 // Length modifier 599 os << LM.toString(); 600 // Conversion specifier 601 os << CS.toString(); 602 } 603 604 bool PrintfSpecifier::hasValidPlusPrefix() const { 605 if (!HasPlusPrefix) 606 return true; 607 608 // The plus prefix only makes sense for signed conversions 609 switch (CS.getKind()) { 610 case ConversionSpecifier::dArg: 611 case ConversionSpecifier::DArg: 612 case ConversionSpecifier::iArg: 613 case ConversionSpecifier::fArg: 614 case ConversionSpecifier::FArg: 615 case ConversionSpecifier::eArg: 616 case ConversionSpecifier::EArg: 617 case ConversionSpecifier::gArg: 618 case ConversionSpecifier::GArg: 619 case ConversionSpecifier::aArg: 620 case ConversionSpecifier::AArg: 621 return true; 622 623 default: 624 return false; 625 } 626 } 627 628 bool PrintfSpecifier::hasValidAlternativeForm() const { 629 if (!HasAlternativeForm) 630 return true; 631 632 // Alternate form flag only valid with the oxXaAeEfFgG conversions 633 switch (CS.getKind()) { 634 case ConversionSpecifier::oArg: 635 case ConversionSpecifier::OArg: 636 case ConversionSpecifier::xArg: 637 case ConversionSpecifier::XArg: 638 case ConversionSpecifier::aArg: 639 case ConversionSpecifier::AArg: 640 case ConversionSpecifier::eArg: 641 case ConversionSpecifier::EArg: 642 case ConversionSpecifier::fArg: 643 case ConversionSpecifier::FArg: 644 case ConversionSpecifier::gArg: 645 case ConversionSpecifier::GArg: 646 return true; 647 648 default: 649 return false; 650 } 651 } 652 653 bool PrintfSpecifier::hasValidLeadingZeros() const { 654 if (!HasLeadingZeroes) 655 return true; 656 657 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions 658 switch (CS.getKind()) { 659 case ConversionSpecifier::dArg: 660 case ConversionSpecifier::DArg: 661 case ConversionSpecifier::iArg: 662 case ConversionSpecifier::oArg: 663 case ConversionSpecifier::OArg: 664 case ConversionSpecifier::uArg: 665 case ConversionSpecifier::UArg: 666 case ConversionSpecifier::xArg: 667 case ConversionSpecifier::XArg: 668 case ConversionSpecifier::aArg: 669 case ConversionSpecifier::AArg: 670 case ConversionSpecifier::eArg: 671 case ConversionSpecifier::EArg: 672 case ConversionSpecifier::fArg: 673 case ConversionSpecifier::FArg: 674 case ConversionSpecifier::gArg: 675 case ConversionSpecifier::GArg: 676 return true; 677 678 default: 679 return false; 680 } 681 } 682 683 bool PrintfSpecifier::hasValidSpacePrefix() const { 684 if (!HasSpacePrefix) 685 return true; 686 687 // The space prefix only makes sense for signed conversions 688 switch (CS.getKind()) { 689 case ConversionSpecifier::dArg: 690 case ConversionSpecifier::DArg: 691 case ConversionSpecifier::iArg: 692 case ConversionSpecifier::fArg: 693 case ConversionSpecifier::FArg: 694 case ConversionSpecifier::eArg: 695 case ConversionSpecifier::EArg: 696 case ConversionSpecifier::gArg: 697 case ConversionSpecifier::GArg: 698 case ConversionSpecifier::aArg: 699 case ConversionSpecifier::AArg: 700 return true; 701 702 default: 703 return false; 704 } 705 } 706 707 bool PrintfSpecifier::hasValidLeftJustified() const { 708 if (!IsLeftJustified) 709 return true; 710 711 // The left justified flag is valid for all conversions except n 712 switch (CS.getKind()) { 713 case ConversionSpecifier::nArg: 714 return false; 715 716 default: 717 return true; 718 } 719 } 720 721 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const { 722 if (!HasThousandsGrouping) 723 return true; 724 725 switch (CS.getKind()) { 726 case ConversionSpecifier::dArg: 727 case ConversionSpecifier::DArg: 728 case ConversionSpecifier::iArg: 729 case ConversionSpecifier::uArg: 730 case ConversionSpecifier::UArg: 731 case ConversionSpecifier::fArg: 732 case ConversionSpecifier::FArg: 733 case ConversionSpecifier::gArg: 734 case ConversionSpecifier::GArg: 735 return true; 736 default: 737 return false; 738 } 739 } 740 741 bool PrintfSpecifier::hasValidPrecision() const { 742 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified) 743 return true; 744 745 // Precision is only valid with the diouxXaAeEfFgGs conversions 746 switch (CS.getKind()) { 747 case ConversionSpecifier::dArg: 748 case ConversionSpecifier::DArg: 749 case ConversionSpecifier::iArg: 750 case ConversionSpecifier::oArg: 751 case ConversionSpecifier::OArg: 752 case ConversionSpecifier::uArg: 753 case ConversionSpecifier::UArg: 754 case ConversionSpecifier::xArg: 755 case ConversionSpecifier::XArg: 756 case ConversionSpecifier::aArg: 757 case ConversionSpecifier::AArg: 758 case ConversionSpecifier::eArg: 759 case ConversionSpecifier::EArg: 760 case ConversionSpecifier::fArg: 761 case ConversionSpecifier::FArg: 762 case ConversionSpecifier::gArg: 763 case ConversionSpecifier::GArg: 764 case ConversionSpecifier::sArg: 765 return true; 766 767 default: 768 return false; 769 } 770 } 771 bool PrintfSpecifier::hasValidFieldWidth() const { 772 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified) 773 return true; 774 775 // The field width is valid for all conversions except n 776 switch (CS.getKind()) { 777 case ConversionSpecifier::nArg: 778 return false; 779 780 default: 781 return true; 782 } 783 } 784