PrintfFormatString.cpp revision 221345
1168404Spjd//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==// 2168404Spjd// 3168404Spjd// The LLVM Compiler Infrastructure 4168404Spjd// 5168404Spjd// This file is distributed under the University of Illinois Open Source 6168404Spjd// License. See LICENSE.TXT for details. 7168404Spjd// 8168404Spjd//===----------------------------------------------------------------------===// 9168404Spjd// 10168404Spjd// Handling of format string in printf and friends. The structure of format 11168404Spjd// strings for fprintf() are described in C99 7.19.6.1. 12168404Spjd// 13168404Spjd//===----------------------------------------------------------------------===// 14168404Spjd 15168404Spjd#include "clang/Analysis/Analyses/FormatString.h" 16168404Spjd#include "FormatStringParsing.h" 17168404Spjd 18168404Spjdusing clang::analyze_format_string::ArgTypeResult; 19168404Spjdusing clang::analyze_format_string::FormatStringHandler; 20168404Spjdusing clang::analyze_format_string::LengthModifier; 21168404Spjdusing clang::analyze_format_string::OptionalAmount; 22185029Spjdusing clang::analyze_format_string::ConversionSpecifier; 23168404Spjdusing clang::analyze_printf::PrintfSpecifier; 24168404Spjd 25168404Spjdusing namespace clang; 26168404Spjd 27168404Spjdtypedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier> 28168404Spjd PrintfSpecifierResult; 29168404Spjd 30168404Spjd//===----------------------------------------------------------------------===// 31168404Spjd// Methods for parsing format strings. 32168404Spjd//===----------------------------------------------------------------------===// 33168404Spjd 34168404Spjdusing analyze_format_string::ParseNonPositionAmount; 35168404Spjd 36168404Spjdstatic bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS, 37185029Spjd const char *Start, const char *&Beg, const char *E, 38185029Spjd unsigned *argIndex) { 39185029Spjd if (argIndex) { 40168404Spjd FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex)); 41185029Spjd } 42168404Spjd else { 43168404Spjd const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 44185029Spjd analyze_format_string::PrecisionPos); 45185029Spjd if (Amt.isInvalid()) 46185029Spjd return true; 47185029Spjd FS.setPrecision(Amt); 48185029Spjd } 49185029Spjd return false; 50185029Spjd} 51185029Spjd 52185029Spjdstatic PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, 53185029Spjd const char *&Beg, 54185029Spjd const char *E, 55185029Spjd unsigned &argIndex, 56185029Spjd bool FormatExtensions) { 57185029Spjd 58185029Spjd using namespace clang::analyze_format_string; 59185029Spjd using namespace clang::analyze_printf; 60185029Spjd 61185029Spjd const char *I = Beg; 62185029Spjd const char *Start = 0; 63185029Spjd UpdateOnReturn <const char*> UpdateBeg(Beg, I); 64185029Spjd 65185029Spjd // Look for a '%' character that indicates the start of a format specifier. 66185029Spjd for ( ; I != E ; ++I) { 67185029Spjd char c = *I; 68185029Spjd if (c == '\0') { 69185029Spjd // Detect spurious null characters, which are likely errors. 70185029Spjd H.HandleNullChar(I); 71185029Spjd return true; 72185029Spjd } 73185029Spjd if (c == '%') { 74185029Spjd Start = I++; // Record the start of the format specifier. 75185029Spjd break; 76185029Spjd } 77185029Spjd } 78185029Spjd 79185029Spjd // No format specifier found? 80185029Spjd if (!Start) 81185029Spjd return false; 82185029Spjd 83185029Spjd if (I == E) { 84185029Spjd // No more characters left? 85185029Spjd H.HandleIncompleteSpecifier(Start, E - Start); 86185029Spjd return true; 87185029Spjd } 88185029Spjd 89185029Spjd PrintfSpecifier FS; 90185029Spjd if (ParseArgPosition(H, FS, Start, I, E)) 91185029Spjd return true; 92185029Spjd 93185029Spjd if (I == E) { 94185029Spjd // No more characters left? 95185029Spjd H.HandleIncompleteSpecifier(Start, E - Start); 96185029Spjd return true; 97185029Spjd } 98185029Spjd 99185029Spjd // Look for flags (if any). 100185029Spjd bool hasMore = true; 101185029Spjd for ( ; I != E; ++I) { 102185029Spjd switch (*I) { 103185029Spjd default: hasMore = false; break; 104185029Spjd case '\'': 105185029Spjd // FIXME: POSIX specific. Always accept? 106185029Spjd FS.setHasThousandsGrouping(I); 107185029Spjd break; 108185029Spjd case '-': FS.setIsLeftJustified(I); break; 109185029Spjd case '+': FS.setHasPlusPrefix(I); break; 110185029Spjd case ' ': FS.setHasSpacePrefix(I); break; 111185029Spjd case '#': FS.setHasAlternativeForm(I); break; 112185029Spjd case '0': FS.setHasLeadingZeros(I); break; 113185029Spjd } 114185029Spjd if (!hasMore) 115185029Spjd break; 116185029Spjd } 117185029Spjd 118185029Spjd if (I == E) { 119185029Spjd // No more characters left? 120185029Spjd H.HandleIncompleteSpecifier(Start, E - Start); 121185029Spjd return true; 122185029Spjd } 123185029Spjd 124185029Spjd // Look for the field width (if any). 125185029Spjd if (ParseFieldWidth(H, FS, Start, I, E, 126185029Spjd FS.usesPositionalArg() ? 0 : &argIndex)) 127185029Spjd return true; 128185029Spjd 129185029Spjd if (I == E) { 130185029Spjd // No more characters left? 131185029Spjd H.HandleIncompleteSpecifier(Start, E - Start); 132185029Spjd return true; 133185029Spjd } 134185029Spjd 135185029Spjd // Look for the precision (if any). 136168404Spjd if (*I == '.') { 137168404Spjd ++I; 138168404Spjd if (I == E) { 139168404Spjd H.HandleIncompleteSpecifier(Start, E - Start); 140168404Spjd return true; 141168404Spjd } 142185029Spjd 143168404Spjd if (ParsePrecision(H, FS, Start, I, E, 144168404Spjd FS.usesPositionalArg() ? 0 : &argIndex)) 145168404Spjd return true; 146168404Spjd 147168404Spjd if (I == E) { 148168404Spjd // No more characters left? 149168404Spjd H.HandleIncompleteSpecifier(Start, E - Start); 150168404Spjd return true; 151168404Spjd } 152168404Spjd } 153168404Spjd 154168404Spjd // Look for the length modifier. 155168404Spjd if (ParseLengthModifier(FS, I, E) && I == E) { 156168404Spjd // No more characters left? 157168404Spjd H.HandleIncompleteSpecifier(Start, E - Start); 158168404Spjd return true; 159168404Spjd } 160168404Spjd 161168404Spjd if (*I == '\0') { 162168404Spjd // Detect spurious null characters, which are likely errors. 163168404Spjd H.HandleNullChar(I); 164168404Spjd return true; 165168404Spjd } 166168404Spjd 167168404Spjd // Finally, look for the conversion specifier. 168168404Spjd const char *conversionPosition = I++; 169168404Spjd ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 170168404Spjd switch (*conversionPosition) { 171168404Spjd default: 172168404Spjd break; 173168404Spjd // C99: 7.19.6.1 (section 8). 174168404Spjd case '%': k = ConversionSpecifier::PercentArg; break; 175168404Spjd case 'A': k = ConversionSpecifier::AArg; break; 176168404Spjd case 'E': k = ConversionSpecifier::EArg; break; 177168404Spjd case 'F': k = ConversionSpecifier::FArg; break; 178168404Spjd case 'G': k = ConversionSpecifier::GArg; break; 179168404Spjd case 'X': k = ConversionSpecifier::XArg; break; 180168404Spjd case 'a': k = ConversionSpecifier::aArg; break; 181168404Spjd case 'c': k = ConversionSpecifier::cArg; break; 182168404Spjd case 'd': k = ConversionSpecifier::dArg; break; 183168404Spjd case 'e': k = ConversionSpecifier::eArg; break; 184168404Spjd case 'f': k = ConversionSpecifier::fArg; break; 185168404Spjd case 'g': k = ConversionSpecifier::gArg; break; 186168404Spjd case 'i': k = ConversionSpecifier::iArg; break; 187168404Spjd case 'n': k = ConversionSpecifier::nArg; break; 188168404Spjd case 'o': k = ConversionSpecifier::oArg; break; 189168404Spjd case 'p': k = ConversionSpecifier::pArg; break; 190168404Spjd case 's': k = ConversionSpecifier::sArg; break; 191168404Spjd case 'u': k = ConversionSpecifier::uArg; break; 192168404Spjd case 'x': k = ConversionSpecifier::xArg; break; 193168404Spjd // POSIX specific. 194168404Spjd case 'C': k = ConversionSpecifier::CArg; break; 195168404Spjd case 'S': k = ConversionSpecifier::SArg; break; 196168404Spjd // Objective-C. 197168404Spjd case '@': k = ConversionSpecifier::ObjCObjArg; break; 198168404Spjd // Glibc specific. 199168404Spjd case 'm': k = ConversionSpecifier::PrintErrno; break; 200168404Spjd // FreeBSD format extensions 201185029Spjd case 'b': if (FormatExtensions) k = ConversionSpecifier::bArg; break; /* check for int and then char * */ 202168404Spjd case 'r': if (FormatExtensions) k = ConversionSpecifier::rArg; break; 203168404Spjd case 'y': if (FormatExtensions) k = ConversionSpecifier::iArg; break; 204168404Spjd case 'D': if (FormatExtensions) k = ConversionSpecifier::DArg; break; /* check for u_char * pointer and a char * string */ 205168404Spjd } 206185029Spjd PrintfConversionSpecifier CS(conversionPosition, k); 207168404Spjd FS.setConversionSpecifier(CS); 208185029Spjd if (CS.consumesDataArgument() && !FS.usesPositionalArg()) 209185029Spjd FS.setArgIndex(argIndex++); 210168404Spjd // FreeBSD extension 211185029Spjd if (k == ConversionSpecifier::bArg || k == ConversionSpecifier::DArg) 212168404Spjd argIndex++; 213168404Spjd 214185029Spjd if (k == ConversionSpecifier::InvalidSpecifier) { 215168404Spjd // Assume the conversion takes one argument. 216168404Spjd return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start); 217185029Spjd } 218168404Spjd return PrintfSpecifierResult(Start, FS); 219168404Spjd} 220168404Spjd 221185029Spjdbool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H, 222185029Spjd const char *I, 223168404Spjd const char *E, 224168404Spjd bool FormatExtensions) { 225185029Spjd 226185029Spjd unsigned argIndex = 0; 227185029Spjd 228185029Spjd // Keep looking for a format specifier until we have exhausted the string. 229168404Spjd while (I != E) { 230168404Spjd const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 231168404Spjd FormatExtensions); 232168404Spjd // Did a fail-stop error of any kind occur when parsing the specifier? 233168404Spjd // If so, don't do any more processing. 234168404Spjd if (FSR.shouldStop()) 235168404Spjd return true;; 236168404Spjd // Did we exhaust the string or encounter an error that 237168404Spjd // we can recover from? 238168404Spjd if (!FSR.hasValue()) 239168404Spjd continue; 240168404Spjd // We have a format specifier. Pass it to the callback. 241168404Spjd if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(), 242168404Spjd I - FSR.getStart())) 243168404Spjd return true; 244168404Spjd } 245168404Spjd assert(I == E && "Format string not exhausted"); 246168404Spjd return false; 247168404Spjd} 248168404Spjd 249168404Spjd//===----------------------------------------------------------------------===// 250168404Spjd// Methods on ConversionSpecifier. 251168404Spjd//===----------------------------------------------------------------------===// 252168404Spjdconst char *ConversionSpecifier::toString() const { 253168404Spjd switch (kind) { 254168404Spjd case dArg: return "d"; 255168404Spjd case iArg: return "i"; 256168404Spjd case oArg: return "o"; 257168404Spjd case uArg: return "u"; 258168404Spjd case xArg: return "x"; 259168404Spjd case XArg: return "X"; 260168404Spjd case fArg: return "f"; 261168404Spjd case FArg: return "F"; 262168404Spjd case eArg: return "e"; 263168404Spjd case EArg: return "E"; 264168404Spjd case gArg: return "g"; 265168404Spjd case GArg: return "G"; 266168404Spjd case aArg: return "a"; 267168404Spjd case AArg: return "A"; 268168404Spjd case cArg: return "c"; 269168404Spjd case sArg: return "s"; 270168404Spjd case pArg: return "p"; 271168404Spjd case nArg: return "n"; 272168404Spjd case PercentArg: return "%"; 273168404Spjd case ScanListArg: return "["; 274168404Spjd case InvalidSpecifier: return NULL; 275168404Spjd 276168404Spjd // MacOS X unicode extensions. 277168404Spjd case CArg: return "C"; 278168404Spjd case SArg: return "S"; 279168404Spjd 280168404Spjd // Objective-C specific specifiers. 281168404Spjd case ObjCObjArg: return "@"; 282168404Spjd 283168404Spjd // FreeBSD specific specifiers. 284168404Spjd case bArg: return "b"; 285168404Spjd case DArg: return "D"; 286168404Spjd case rArg: return "r"; 287168404Spjd 288168404Spjd // GlibC specific specifiers. 289168404Spjd case PrintErrno: return "m"; 290168404Spjd } 291168404Spjd return NULL; 292168404Spjd} 293168404Spjd 294168404Spjd//===----------------------------------------------------------------------===// 295185029Spjd// Methods on PrintfSpecifier. 296168404Spjd//===----------------------------------------------------------------------===// 297168404Spjd 298168404SpjdArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const { 299168404Spjd const PrintfConversionSpecifier &CS = getConversionSpecifier(); 300168404Spjd 301168404Spjd if (!CS.consumesDataArgument()) 302168404Spjd return ArgTypeResult::Invalid(); 303168404Spjd 304168404Spjd if (CS.getKind() == ConversionSpecifier::cArg) 305168404Spjd switch (LM.getKind()) { 306168404Spjd case LengthModifier::None: return Ctx.IntTy; 307168404Spjd case LengthModifier::AsLong: return ArgTypeResult::WIntTy; 308168404Spjd default: 309168404Spjd return ArgTypeResult::Invalid(); 310168404Spjd } 311172443Spjd 312172443Spjd if (CS.isIntArg()) 313168404Spjd switch (LM.getKind()) { 314168404Spjd case LengthModifier::AsLongDouble: 315168404Spjd return ArgTypeResult::Invalid(); 316168404Spjd case LengthModifier::None: return Ctx.IntTy; 317168404Spjd case LengthModifier::AsChar: return Ctx.SignedCharTy; 318168404Spjd case LengthModifier::AsShort: return Ctx.ShortTy; 319168404Spjd case LengthModifier::AsLong: return Ctx.LongTy; 320168404Spjd case LengthModifier::AsLongLong: return Ctx.LongLongTy; 321185029Spjd case LengthModifier::AsIntMax: 322168404Spjd // FIXME: Return unknown for now. 323168404Spjd return ArgTypeResult(); 324168404Spjd case LengthModifier::AsSizeT: return Ctx.getSizeType(); 325168404Spjd case LengthModifier::AsPtrDiff: return Ctx.getPointerDiffType(); 326168404Spjd } 327168404Spjd 328168404Spjd if (CS.isUIntArg()) 329168404Spjd switch (LM.getKind()) { 330185029Spjd case LengthModifier::AsLongDouble: 331185029Spjd return ArgTypeResult::Invalid(); 332168404Spjd case LengthModifier::None: return Ctx.UnsignedIntTy; 333185029Spjd case LengthModifier::AsChar: return Ctx.UnsignedCharTy; 334185029Spjd case LengthModifier::AsShort: return Ctx.UnsignedShortTy; 335185029Spjd case LengthModifier::AsLong: return Ctx.UnsignedLongTy; 336185029Spjd case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy; 337168404Spjd case LengthModifier::AsIntMax: 338168404Spjd // FIXME: Return unknown for now. 339168404Spjd return ArgTypeResult(); 340168404Spjd case LengthModifier::AsSizeT: 341185029Spjd // FIXME: How to get the corresponding unsigned 342168404Spjd // version of size_t? 343168404Spjd return ArgTypeResult(); 344168404Spjd case LengthModifier::AsPtrDiff: 345168404Spjd // FIXME: How to get the corresponding unsigned 346168404Spjd // version of ptrdiff_t? 347168404Spjd return ArgTypeResult(); 348168404Spjd } 349168404Spjd 350168404Spjd if (CS.isDoubleArg()) { 351168404Spjd if (LM.getKind() == LengthModifier::AsLongDouble) 352168404Spjd return Ctx.LongDoubleTy; 353168404Spjd return Ctx.DoubleTy; 354168404Spjd } 355168404Spjd 356168404Spjd switch (CS.getKind()) { 357168404Spjd case ConversionSpecifier::sArg: 358168404Spjd return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ? 359168404Spjd ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy); 360168404Spjd case ConversionSpecifier::SArg: 361168404Spjd // FIXME: This appears to be Mac OS X specific. 362168404Spjd return ArgTypeResult::WCStrTy; 363168404Spjd case ConversionSpecifier::CArg: 364168404Spjd return Ctx.WCharTy; 365168404Spjd case ConversionSpecifier::pArg: 366168404Spjd return ArgTypeResult::CPointerTy; 367168404Spjd default: 368185029Spjd break; 369168404Spjd } 370168404Spjd 371168404Spjd // FIXME: Handle other cases. 372168404Spjd return ArgTypeResult(); 373168404Spjd} 374168404Spjd 375168404Spjdbool PrintfSpecifier::fixType(QualType QT) { 376168404Spjd // Handle strings first (char *, wchar_t *) 377168404Spjd if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { 378168404Spjd CS.setKind(ConversionSpecifier::sArg); 379168404Spjd 380168404Spjd // Disable irrelevant flags 381168404Spjd HasAlternativeForm = 0; 382168404Spjd HasLeadingZeroes = 0; 383168404Spjd 384168404Spjd // Set the long length modifier for wide characters 385168404Spjd if (QT->getPointeeType()->isWideCharType()) 386168404Spjd LM.setKind(LengthModifier::AsWideChar); 387168404Spjd 388168404Spjd return true; 389168404Spjd } 390168404Spjd 391168404Spjd // We can only work with builtin types. 392168404Spjd if (!QT->isBuiltinType()) 393168404Spjd return false; 394168404Spjd 395168404Spjd // Everything else should be a base type 396168404Spjd const BuiltinType *BT = QT->getAs<BuiltinType>(); 397168404Spjd 398168404Spjd // Set length modifier 399168404Spjd switch (BT->getKind()) { 400168404Spjd case BuiltinType::Bool: 401168404Spjd case BuiltinType::WChar_U: 402168404Spjd case BuiltinType::WChar_S: 403168404Spjd case BuiltinType::Char16: 404168404Spjd case BuiltinType::Char32: 405168404Spjd case BuiltinType::UInt128: 406168404Spjd case BuiltinType::Int128: 407168404Spjd // Integral types which are non-trivial to correct. 408168404Spjd return false; 409168404Spjd 410168404Spjd case BuiltinType::Void: 411168404Spjd case BuiltinType::NullPtr: 412168404Spjd case BuiltinType::ObjCId: 413168404Spjd case BuiltinType::ObjCClass: 414168404Spjd case BuiltinType::ObjCSel: 415168404Spjd case BuiltinType::Dependent: 416168404Spjd case BuiltinType::Overload: 417168404Spjd case BuiltinType::BoundMember: 418168404Spjd case BuiltinType::UnknownAny: 419168404Spjd // Misc other stuff which doesn't make sense here. 420185029Spjd return false; 421168404Spjd 422168404Spjd case BuiltinType::UInt: 423168404Spjd case BuiltinType::Int: 424168404Spjd case BuiltinType::Float: 425168404Spjd case BuiltinType::Double: 426168404Spjd LM.setKind(LengthModifier::None); 427185029Spjd break; 428168404Spjd 429168404Spjd case BuiltinType::Char_U: 430168404Spjd case BuiltinType::UChar: 431168404Spjd case BuiltinType::Char_S: 432168404Spjd case BuiltinType::SChar: 433168404Spjd LM.setKind(LengthModifier::AsChar); 434168404Spjd break; 435168404Spjd 436168404Spjd case BuiltinType::Short: 437168404Spjd case BuiltinType::UShort: 438168404Spjd LM.setKind(LengthModifier::AsShort); 439168404Spjd break; 440168404Spjd 441168404Spjd case BuiltinType::Long: 442168404Spjd case BuiltinType::ULong: 443168404Spjd LM.setKind(LengthModifier::AsLong); 444168404Spjd break; 445168404Spjd 446185029Spjd case BuiltinType::LongLong: 447185029Spjd case BuiltinType::ULongLong: 448168404Spjd LM.setKind(LengthModifier::AsLongLong); 449168404Spjd break; 450168404Spjd 451185029Spjd case BuiltinType::LongDouble: 452168404Spjd LM.setKind(LengthModifier::AsLongDouble); 453168404Spjd break; 454168404Spjd } 455168404Spjd 456168404Spjd // Set conversion specifier and disable any flags which do not apply to it. 457168404Spjd // Let typedefs to char fall through to int, as %c is silly for uint8_t. 458168404Spjd if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) { 459168404Spjd CS.setKind(ConversionSpecifier::cArg); 460168404Spjd LM.setKind(LengthModifier::None); 461168404Spjd Precision.setHowSpecified(OptionalAmount::NotSpecified); 462185029Spjd HasAlternativeForm = 0; 463185029Spjd HasLeadingZeroes = 0; 464185029Spjd HasPlusPrefix = 0; 465185029Spjd } 466168404Spjd // Test for Floating type first as LongDouble can pass isUnsignedIntegerType 467168404Spjd else if (QT->isRealFloatingType()) { 468168404Spjd CS.setKind(ConversionSpecifier::fArg); 469185029Spjd } 470168404Spjd else if (QT->isSignedIntegerType()) { 471168404Spjd CS.setKind(ConversionSpecifier::dArg); 472168404Spjd HasAlternativeForm = 0; 473168404Spjd } 474168404Spjd else if (QT->isUnsignedIntegerType()) { 475168404Spjd // Preserve the original formatting, e.g. 'X', 'o'. 476168404Spjd if (!cast<PrintfConversionSpecifier>(CS).isUIntArg()) 477185029Spjd CS.setKind(ConversionSpecifier::uArg); 478168404Spjd HasAlternativeForm = 0; 479168404Spjd HasPlusPrefix = 0; 480168404Spjd } 481168404Spjd else { 482185029Spjd assert(0 && "Unexpected type"); 483185029Spjd } 484185029Spjd 485185029Spjd return true; 486185029Spjd} 487185029Spjd 488168404Spjdvoid PrintfSpecifier::toString(llvm::raw_ostream &os) const { 489168404Spjd // Whilst some features have no defined order, we are using the order 490185029Spjd // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1) 491185029Spjd os << "%"; 492168404Spjd 493168404Spjd // Positional args 494168404Spjd if (usesPositionalArg()) { 495185029Spjd os << getPositionalArgIndex() << "$"; 496168404Spjd } 497168404Spjd 498168404Spjd // Conversion flags 499168404Spjd if (IsLeftJustified) os << "-"; 500168404Spjd if (HasPlusPrefix) os << "+"; 501168404Spjd if (HasSpacePrefix) os << " "; 502168404Spjd if (HasAlternativeForm) os << "#"; 503168404Spjd if (HasLeadingZeroes) os << "0"; 504168404Spjd 505168404Spjd // Minimum field width 506168404Spjd FieldWidth.toString(os); 507168404Spjd // Precision 508168404Spjd Precision.toString(os); 509168404Spjd // Length modifier 510168404Spjd os << LM.toString(); 511168404Spjd // Conversion specifier 512168404Spjd os << CS.toString(); 513168404Spjd} 514185029Spjd 515168404Spjdbool PrintfSpecifier::hasValidPlusPrefix() const { 516168404Spjd if (!HasPlusPrefix) 517168404Spjd return true; 518168404Spjd 519168404Spjd // The plus prefix only makes sense for signed conversions 520168404Spjd switch (CS.getKind()) { 521168404Spjd case ConversionSpecifier::dArg: 522185029Spjd case ConversionSpecifier::iArg: 523185029Spjd case ConversionSpecifier::fArg: 524185029Spjd case ConversionSpecifier::FArg: 525185029Spjd case ConversionSpecifier::eArg: 526185029Spjd case ConversionSpecifier::EArg: 527185029Spjd case ConversionSpecifier::gArg: 528185029Spjd case ConversionSpecifier::GArg: 529185029Spjd case ConversionSpecifier::aArg: 530185029Spjd case ConversionSpecifier::AArg: 531168404Spjd case ConversionSpecifier::rArg: 532168404Spjd return true; 533168404Spjd 534168404Spjd default: 535168404Spjd return false; 536185029Spjd } 537168404Spjd} 538168404Spjd 539168404Spjdbool PrintfSpecifier::hasValidAlternativeForm() const { 540168404Spjd if (!HasAlternativeForm) 541168404Spjd return true; 542168404Spjd 543168404Spjd // Alternate form flag only valid with the oxXaAeEfFgG conversions 544185029Spjd switch (CS.getKind()) { 545185029Spjd case ConversionSpecifier::oArg: 546185029Spjd case ConversionSpecifier::xArg: 547185029Spjd case ConversionSpecifier::XArg: 548185029Spjd case ConversionSpecifier::aArg: 549185029Spjd case ConversionSpecifier::AArg: 550185029Spjd case ConversionSpecifier::eArg: 551168404Spjd case ConversionSpecifier::EArg: 552168404Spjd case ConversionSpecifier::fArg: 553185029Spjd case ConversionSpecifier::FArg: 554168404Spjd case ConversionSpecifier::gArg: 555168404Spjd case ConversionSpecifier::GArg: 556168404Spjd case ConversionSpecifier::rArg: 557168404Spjd return true; 558168404Spjd 559168404Spjd default: 560168404Spjd return false; 561168404Spjd } 562168404Spjd} 563168404Spjd 564168404Spjdbool PrintfSpecifier::hasValidLeadingZeros() const { 565168404Spjd if (!HasLeadingZeroes) 566168404Spjd return true; 567168404Spjd 568168404Spjd // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions 569168404Spjd switch (CS.getKind()) { 570168404Spjd case ConversionSpecifier::dArg: 571168404Spjd case ConversionSpecifier::iArg: 572168404Spjd case ConversionSpecifier::oArg: 573168404Spjd case ConversionSpecifier::uArg: 574168404Spjd case ConversionSpecifier::xArg: 575168404Spjd case ConversionSpecifier::XArg: 576168404Spjd case ConversionSpecifier::aArg: 577168404Spjd case ConversionSpecifier::AArg: 578168404Spjd case ConversionSpecifier::eArg: 579168404Spjd case ConversionSpecifier::EArg: 580168404Spjd case ConversionSpecifier::fArg: 581168404Spjd case ConversionSpecifier::FArg: 582168404Spjd case ConversionSpecifier::gArg: 583168404Spjd case ConversionSpecifier::GArg: 584168404Spjd return true; 585168404Spjd 586168404Spjd default: 587168404Spjd return false; 588168404Spjd } 589168404Spjd} 590168404Spjd 591185029Spjdbool PrintfSpecifier::hasValidSpacePrefix() const { 592168404Spjd if (!HasSpacePrefix) 593168404Spjd return true; 594168404Spjd 595168404Spjd // The space prefix only makes sense for signed conversions 596168404Spjd switch (CS.getKind()) { 597168404Spjd case ConversionSpecifier::dArg: 598168404Spjd case ConversionSpecifier::iArg: 599168404Spjd case ConversionSpecifier::fArg: 600168404Spjd case ConversionSpecifier::FArg: 601168404Spjd case ConversionSpecifier::eArg: 602168404Spjd case ConversionSpecifier::EArg: 603168404Spjd case ConversionSpecifier::gArg: 604185029Spjd case ConversionSpecifier::GArg: 605185029Spjd case ConversionSpecifier::aArg: 606168404Spjd case ConversionSpecifier::AArg: 607185029Spjd return true; 608185029Spjd 609185029Spjd default: 610185029Spjd return false; 611185029Spjd } 612185029Spjd} 613168404Spjd 614185029Spjdbool PrintfSpecifier::hasValidLeftJustified() const { 615185029Spjd if (!IsLeftJustified) 616185029Spjd return true; 617185029Spjd 618185029Spjd // The left justified flag is valid for all conversions except n 619185029Spjd switch (CS.getKind()) { 620185029Spjd case ConversionSpecifier::nArg: 621185029Spjd return false; 622185029Spjd 623185029Spjd default: 624185029Spjd return true; 625185029Spjd } 626185029Spjd} 627185029Spjd 628185029Spjdbool PrintfSpecifier::hasValidThousandsGroupingPrefix() const { 629185029Spjd if (!HasThousandsGrouping) 630185029Spjd return true; 631185029Spjd 632185029Spjd switch (CS.getKind()) { 633185029Spjd case ConversionSpecifier::dArg: 634185029Spjd case ConversionSpecifier::iArg: 635185029Spjd case ConversionSpecifier::uArg: 636185029Spjd case ConversionSpecifier::fArg: 637185029Spjd case ConversionSpecifier::FArg: 638185029Spjd case ConversionSpecifier::gArg: 639185029Spjd case ConversionSpecifier::GArg: 640185029Spjd return true; 641185029Spjd default: 642185029Spjd return false; 643185029Spjd } 644185029Spjd} 645185029Spjd 646185029Spjdbool PrintfSpecifier::hasValidPrecision() const { 647185029Spjd if (Precision.getHowSpecified() == OptionalAmount::NotSpecified) 648168404Spjd return true; 649168404Spjd 650168404Spjd // Precision is only valid with the diouxXaAeEfFgGs conversions 651168404Spjd switch (CS.getKind()) { 652185029Spjd case ConversionSpecifier::dArg: 653185029Spjd case ConversionSpecifier::iArg: 654185029Spjd case ConversionSpecifier::oArg: 655185029Spjd case ConversionSpecifier::uArg: 656185029Spjd case ConversionSpecifier::xArg: 657185029Spjd case ConversionSpecifier::XArg: 658185029Spjd case ConversionSpecifier::aArg: 659185029Spjd case ConversionSpecifier::AArg: 660185029Spjd case ConversionSpecifier::eArg: 661185029Spjd case ConversionSpecifier::EArg: 662168404Spjd case ConversionSpecifier::fArg: 663168404Spjd case ConversionSpecifier::FArg: 664168404Spjd case ConversionSpecifier::gArg: 665185029Spjd case ConversionSpecifier::GArg: 666168404Spjd case ConversionSpecifier::sArg: 667185029Spjd return true; 668168404Spjd 669168404Spjd default: 670185029Spjd return false; 671185029Spjd } 672185029Spjd} 673185029Spjdbool PrintfSpecifier::hasValidFieldWidth() const { 674185029Spjd if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified) 675185029Spjd return true; 676168404Spjd 677185029Spjd // The field width is valid for all conversions except n 678185029Spjd switch (CS.getKind()) { 679168404Spjd case ConversionSpecifier::nArg: 680185029Spjd return false; 681168404Spjd 682168404Spjd default: 683168404Spjd return true; 684185029Spjd } 685168404Spjd} 686185029Spjd