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