PrintfFormatString.cpp revision 0c293ea13d452c1a47a05ada5a5ee9acc69c66cc
1//= PrintfFormatStrings.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/PrintfFormatString.h" 16#include "clang/AST/ASTContext.h" 17#include "clang/AST/Type.h" 18#include "llvm/Support/raw_ostream.h" 19 20using clang::analyze_printf::ArgTypeResult; 21using clang::analyze_printf::FormatSpecifier; 22using clang::analyze_printf::FormatStringHandler; 23using clang::analyze_printf::OptionalAmount; 24using clang::analyze_printf::PositionContext; 25using clang::analyze_printf::ConversionSpecifier; 26using clang::analyze_printf::LengthModifier; 27 28using namespace clang; 29 30namespace { 31class FormatSpecifierResult { 32 FormatSpecifier FS; 33 const char *Start; 34 bool Stop; 35public: 36 FormatSpecifierResult(bool stop = false) 37 : Start(0), Stop(stop) {} 38 FormatSpecifierResult(const char *start, 39 const FormatSpecifier &fs) 40 : FS(fs), Start(start), Stop(false) {} 41 42 const char *getStart() const { return Start; } 43 bool shouldStop() const { return Stop; } 44 bool hasValue() const { return Start != 0; } 45 const FormatSpecifier &getValue() const { 46 assert(hasValue()); 47 return FS; 48 } 49 const FormatSpecifier &getValue() { return FS; } 50}; 51} // end anonymous namespace 52 53template <typename T> 54class UpdateOnReturn { 55 T &ValueToUpdate; 56 const T &ValueToCopy; 57public: 58 UpdateOnReturn(T &valueToUpdate, const T &valueToCopy) 59 : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {} 60 61 ~UpdateOnReturn() { 62 ValueToUpdate = ValueToCopy; 63 } 64}; 65 66//===----------------------------------------------------------------------===// 67// Methods for parsing format strings. 68//===----------------------------------------------------------------------===// 69 70static OptionalAmount ParseAmount(const char *&Beg, const char *E) { 71 const char *I = Beg; 72 UpdateOnReturn <const char*> UpdateBeg(Beg, I); 73 74 unsigned accumulator = 0; 75 bool hasDigits = false; 76 77 for ( ; I != E; ++I) { 78 char c = *I; 79 if (c >= '0' && c <= '9') { 80 hasDigits = true; 81 accumulator = (accumulator * 10) + (c - '0'); 82 continue; 83 } 84 85 if (hasDigits) 86 return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg, 87 false); 88 89 break; 90 } 91 92 return OptionalAmount(); 93} 94 95static OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E, 96 unsigned &argIndex) { 97 if (*Beg == '*') { 98 ++Beg; 99 return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false); 100 } 101 102 return ParseAmount(Beg, E); 103} 104 105static OptionalAmount ParsePositionAmount(FormatStringHandler &H, 106 const char *Start, 107 const char *&Beg, const char *E, 108 PositionContext p) { 109 if (*Beg == '*') { 110 const char *I = Beg + 1; 111 const OptionalAmount &Amt = ParseAmount(I, E); 112 113 if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) { 114 H.HandleInvalidPosition(Beg, I - Beg, p); 115 return OptionalAmount(false); 116 } 117 118 if (I== E) { 119 // No more characters left? 120 H.HandleIncompleteFormatSpecifier(Start, E - Start); 121 return OptionalAmount(false); 122 } 123 124 assert(Amt.getHowSpecified() == OptionalAmount::Constant); 125 126 if (*I == '$') { 127 // Handle positional arguments 128 129 // Special case: '*0$', since this is an easy mistake. 130 if (Amt.getConstantAmount() == 0) { 131 H.HandleZeroPosition(Beg, I - Beg + 1); 132 return OptionalAmount(false); 133 } 134 135 const char *Tmp = Beg; 136 Beg = ++I; 137 138 return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1, 139 Tmp, 0, true); 140 } 141 142 H.HandleInvalidPosition(Beg, I - Beg, p); 143 return OptionalAmount(false); 144 } 145 146 return ParseAmount(Beg, E); 147} 148 149static bool ParsePrecision(FormatStringHandler &H, FormatSpecifier &FS, 150 const char *Start, const char *&Beg, const char *E, 151 unsigned *argIndex) { 152 if (argIndex) { 153 FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex)); 154 } 155 else { 156 const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 157 analyze_printf::PrecisionPos); 158 if (Amt.isInvalid()) 159 return true; 160 FS.setPrecision(Amt); 161 } 162 return false; 163} 164 165static bool ParseFieldWidth(FormatStringHandler &H, FormatSpecifier &FS, 166 const char *Start, const char *&Beg, const char *E, 167 unsigned *argIndex) { 168 // FIXME: Support negative field widths. 169 if (argIndex) { 170 FS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex)); 171 } 172 else { 173 const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 174 analyze_printf::FieldWidthPos); 175 if (Amt.isInvalid()) 176 return true; 177 FS.setFieldWidth(Amt); 178 } 179 return false; 180} 181 182static bool ParseArgPosition(FormatStringHandler &H, 183 FormatSpecifier &FS, const char *Start, 184 const char *&Beg, const char *E) { 185 186 using namespace clang::analyze_printf; 187 const char *I = Beg; 188 189 const OptionalAmount &Amt = ParseAmount(I, E); 190 191 if (I == E) { 192 // No more characters left? 193 H.HandleIncompleteFormatSpecifier(Start, E - Start); 194 return true; 195 } 196 197 if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') { 198 // Special case: '%0$', since this is an easy mistake. 199 if (Amt.getConstantAmount() == 0) { 200 H.HandleZeroPosition(Start, I - Start); 201 return true; 202 } 203 204 FS.setArgIndex(Amt.getConstantAmount() - 1); 205 FS.setUsesPositionalArg(); 206 // Update the caller's pointer if we decided to consume 207 // these characters. 208 Beg = I; 209 return false; 210 } 211 212 return false; 213} 214 215static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H, 216 const char *&Beg, 217 const char *E, 218 unsigned &argIndex) { 219 220 using namespace clang::analyze_printf; 221 222 const char *I = Beg; 223 const char *Start = 0; 224 UpdateOnReturn <const char*> UpdateBeg(Beg, I); 225 226 // Look for a '%' character that indicates the start of a format specifier. 227 for ( ; I != E ; ++I) { 228 char c = *I; 229 if (c == '\0') { 230 // Detect spurious null characters, which are likely errors. 231 H.HandleNullChar(I); 232 return true; 233 } 234 if (c == '%') { 235 Start = I++; // Record the start of the format specifier. 236 break; 237 } 238 } 239 240 // No format specifier found? 241 if (!Start) 242 return false; 243 244 if (I == E) { 245 // No more characters left? 246 H.HandleIncompleteFormatSpecifier(Start, E - Start); 247 return true; 248 } 249 250 FormatSpecifier FS; 251 if (ParseArgPosition(H, FS, Start, I, E)) 252 return true; 253 254 if (I == E) { 255 // No more characters left? 256 H.HandleIncompleteFormatSpecifier(Start, E - Start); 257 return true; 258 } 259 260 // Look for flags (if any). 261 bool hasMore = true; 262 for ( ; I != E; ++I) { 263 switch (*I) { 264 default: hasMore = false; break; 265 case '-': FS.setIsLeftJustified(I); break; 266 case '+': FS.setHasPlusPrefix(I); break; 267 case ' ': FS.setHasSpacePrefix(I); break; 268 case '#': FS.setHasAlternativeForm(I); break; 269 case '0': FS.setHasLeadingZeros(I); break; 270 } 271 if (!hasMore) 272 break; 273 } 274 275 if (I == E) { 276 // No more characters left? 277 H.HandleIncompleteFormatSpecifier(Start, E - Start); 278 return true; 279 } 280 281 // Look for the field width (if any). 282 if (ParseFieldWidth(H, FS, Start, I, E, 283 FS.usesPositionalArg() ? 0 : &argIndex)) 284 return true; 285 286 if (I == E) { 287 // No more characters left? 288 H.HandleIncompleteFormatSpecifier(Start, E - Start); 289 return true; 290 } 291 292 // Look for the precision (if any). 293 if (*I == '.') { 294 ++I; 295 if (I == E) { 296 H.HandleIncompleteFormatSpecifier(Start, E - Start); 297 return true; 298 } 299 300 if (ParsePrecision(H, FS, Start, I, E, 301 FS.usesPositionalArg() ? 0 : &argIndex)) 302 return true; 303 304 if (I == E) { 305 // No more characters left? 306 H.HandleIncompleteFormatSpecifier(Start, E - Start); 307 return true; 308 } 309 } 310 311 // Look for the length modifier. 312 LengthModifier::Kind lmKind = LengthModifier::None; 313 const char *lmPosition = I; 314 switch (*I) { 315 default: 316 break; 317 case 'h': 318 ++I; 319 lmKind = (I != E && *I == 'h') ? 320 ++I, LengthModifier::AsChar : LengthModifier::AsShort; 321 break; 322 case 'l': 323 ++I; 324 lmKind = (I != E && *I == 'l') ? 325 ++I, LengthModifier::AsLongLong : LengthModifier::AsLong; 326 break; 327 case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; 328 case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; 329 case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; 330 case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; 331 case 'q': lmKind = LengthModifier::AsLongLong; ++I; break; 332 } 333 LengthModifier lm(lmPosition, lmKind); 334 FS.setLengthModifier(lm); 335 336 if (I == E) { 337 // No more characters left? 338 H.HandleIncompleteFormatSpecifier(Start, E - Start); 339 return true; 340 } 341 342 if (*I == '\0') { 343 // Detect spurious null characters, which are likely errors. 344 H.HandleNullChar(I); 345 return true; 346 } 347 348 // Finally, look for the conversion specifier. 349 const char *conversionPosition = I++; 350 ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 351 switch (*conversionPosition) { 352 default: 353 break; 354 // C99: 7.19.6.1 (section 8). 355 case '%': k = ConversionSpecifier::PercentArg; break; 356 case 'A': k = ConversionSpecifier::AArg; break; 357 case 'E': k = ConversionSpecifier::EArg; break; 358 case 'F': k = ConversionSpecifier::FArg; break; 359 case 'G': k = ConversionSpecifier::GArg; break; 360 case 'X': k = ConversionSpecifier::XArg; break; 361 case 'a': k = ConversionSpecifier::aArg; break; 362 case 'c': k = ConversionSpecifier::IntAsCharArg; break; 363 case 'd': k = ConversionSpecifier::dArg; break; 364 case 'e': k = ConversionSpecifier::eArg; break; 365 case 'f': k = ConversionSpecifier::fArg; break; 366 case 'g': k = ConversionSpecifier::gArg; break; 367 case 'i': k = ConversionSpecifier::iArg; break; 368 case 'n': k = ConversionSpecifier::OutIntPtrArg; break; 369 case 'o': k = ConversionSpecifier::oArg; break; 370 case 'p': k = ConversionSpecifier::VoidPtrArg; break; 371 case 's': k = ConversionSpecifier::CStrArg; break; 372 case 'u': k = ConversionSpecifier::uArg; break; 373 case 'x': k = ConversionSpecifier::xArg; break; 374 // Mac OS X (unicode) specific 375 case 'C': k = ConversionSpecifier::CArg; break; 376 case 'S': k = ConversionSpecifier::UnicodeStrArg; break; 377 // Objective-C. 378 case '@': k = ConversionSpecifier::ObjCObjArg; break; 379 // Glibc specific. 380 case 'm': k = ConversionSpecifier::PrintErrno; break; 381 } 382 ConversionSpecifier CS(conversionPosition, k); 383 FS.setConversionSpecifier(CS); 384 if (CS.consumesDataArgument() && !FS.usesPositionalArg()) 385 FS.setArgIndex(argIndex++); 386 387 if (k == ConversionSpecifier::InvalidSpecifier) { 388 // Assume the conversion takes one argument. 389 return !H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg); 390 } 391 return FormatSpecifierResult(Start, FS); 392} 393 394bool clang::analyze_printf::ParseFormatString(FormatStringHandler &H, 395 const char *I, const char *E) { 396 397 unsigned argIndex = 0; 398 399 // Keep looking for a format specifier until we have exhausted the string. 400 while (I != E) { 401 const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E, argIndex); 402 // Did a fail-stop error of any kind occur when parsing the specifier? 403 // If so, don't do any more processing. 404 if (FSR.shouldStop()) 405 return true;; 406 // Did we exhaust the string or encounter an error that 407 // we can recover from? 408 if (!FSR.hasValue()) 409 continue; 410 // We have a format specifier. Pass it to the callback. 411 if (!H.HandleFormatSpecifier(FSR.getValue(), FSR.getStart(), 412 I - FSR.getStart())) 413 return true; 414 } 415 assert(I == E && "Format string not exhausted"); 416 return false; 417} 418 419FormatStringHandler::~FormatStringHandler() {} 420 421//===----------------------------------------------------------------------===// 422// Methods on ArgTypeResult. 423//===----------------------------------------------------------------------===// 424 425bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { 426 switch (K) { 427 case InvalidTy: 428 assert(false && "ArgTypeResult must be valid"); 429 return true; 430 431 case UnknownTy: 432 return true; 433 434 case SpecificTy: { 435 argTy = C.getCanonicalType(argTy).getUnqualifiedType(); 436 if (T == argTy) 437 return true; 438 if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) 439 switch (BT->getKind()) { 440 default: 441 break; 442 case BuiltinType::Char_S: 443 case BuiltinType::SChar: 444 return T == C.UnsignedCharTy; 445 case BuiltinType::Char_U: 446 case BuiltinType::UChar: 447 return T == C.SignedCharTy; 448 case BuiltinType::Short: 449 return T == C.UnsignedShortTy; 450 case BuiltinType::UShort: 451 return T == C.ShortTy; 452 case BuiltinType::Int: 453 return T == C.UnsignedIntTy; 454 case BuiltinType::UInt: 455 return T == C.IntTy; 456 case BuiltinType::Long: 457 return T == C.UnsignedLongTy; 458 case BuiltinType::ULong: 459 return T == C.LongTy; 460 case BuiltinType::LongLong: 461 return T == C.UnsignedLongLongTy; 462 case BuiltinType::ULongLong: 463 return T == C.LongLongTy; 464 } 465 return false; 466 } 467 468 case CStrTy: { 469 const PointerType *PT = argTy->getAs<PointerType>(); 470 if (!PT) 471 return false; 472 QualType pointeeTy = PT->getPointeeType(); 473 if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) 474 switch (BT->getKind()) { 475 case BuiltinType::Void: 476 case BuiltinType::Char_U: 477 case BuiltinType::UChar: 478 case BuiltinType::Char_S: 479 case BuiltinType::SChar: 480 return true; 481 default: 482 break; 483 } 484 485 return false; 486 } 487 488 case WCStrTy: { 489 const PointerType *PT = argTy->getAs<PointerType>(); 490 if (!PT) 491 return false; 492 QualType pointeeTy = 493 C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); 494 return pointeeTy == C.getWCharType(); 495 } 496 497 case CPointerTy: 498 return argTy->getAs<PointerType>() != NULL || 499 argTy->getAs<ObjCObjectPointerType>() != NULL; 500 501 case ObjCPointerTy: 502 return argTy->getAs<ObjCObjectPointerType>() != NULL; 503 } 504 505 // FIXME: Should be unreachable, but Clang is currently emitting 506 // a warning. 507 return false; 508} 509 510QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const { 511 switch (K) { 512 case InvalidTy: 513 assert(false && "No representative type for Invalid ArgTypeResult"); 514 // Fall-through. 515 case UnknownTy: 516 return QualType(); 517 case SpecificTy: 518 return T; 519 case CStrTy: 520 return C.getPointerType(C.CharTy); 521 case WCStrTy: 522 return C.getPointerType(C.getWCharType()); 523 case ObjCPointerTy: 524 return C.ObjCBuiltinIdTy; 525 case CPointerTy: 526 return C.VoidPtrTy; 527 } 528 529 // FIXME: Should be unreachable, but Clang is currently emitting 530 // a warning. 531 return QualType(); 532} 533 534//===----------------------------------------------------------------------===// 535// Methods on OptionalAmount. 536//===----------------------------------------------------------------------===// 537 538ArgTypeResult OptionalAmount::getArgType(ASTContext &Ctx) const { 539 return Ctx.IntTy; 540} 541 542//===----------------------------------------------------------------------===// 543// Methods on ConversionSpecifier. 544//===----------------------------------------------------------------------===// 545const char *ConversionSpecifier::toString() const { 546 switch (kind) { 547 case dArg: return "d"; 548 case iArg: return "i"; 549 case oArg: return "o"; 550 case uArg: return "u"; 551 case xArg: return "x"; 552 case XArg: return "X"; 553 case fArg: return "f"; 554 case FArg: return "F"; 555 case eArg: return "e"; 556 case EArg: return "E"; 557 case gArg: return "g"; 558 case GArg: return "G"; 559 case aArg: return "a"; 560 case AArg: return "A"; 561 case IntAsCharArg: return "c"; 562 case CStrArg: return "s"; 563 case VoidPtrArg: return "p"; 564 case OutIntPtrArg: return "n"; 565 case PercentArg: return "%"; 566 case InvalidSpecifier: return NULL; 567 568 // MacOS X unicode extensions. 569 case CArg: return "C"; 570 case UnicodeStrArg: return "S"; 571 572 // Objective-C specific specifiers. 573 case ObjCObjArg: return "@"; 574 575 // GlibC specific specifiers. 576 case PrintErrno: return "m"; 577 } 578 return NULL; 579} 580 581//===----------------------------------------------------------------------===// 582// Methods on LengthModifier. 583//===----------------------------------------------------------------------===// 584 585const char *LengthModifier::toString() const { 586 switch (kind) { 587 case AsChar: 588 return "hh"; 589 case AsShort: 590 return "h"; 591 case AsLong: // or AsWideChar 592 return "l"; 593 case AsLongLong: 594 return "ll"; 595 case AsIntMax: 596 return "j"; 597 case AsSizeT: 598 return "z"; 599 case AsPtrDiff: 600 return "t"; 601 case AsLongDouble: 602 return "L"; 603 case None: 604 return ""; 605 } 606 return NULL; 607} 608 609//===----------------------------------------------------------------------===// 610// Methods on OptionalAmount. 611//===----------------------------------------------------------------------===// 612 613void OptionalAmount::toString(llvm::raw_ostream &os) const { 614 switch (hs) { 615 case Invalid: 616 case NotSpecified: 617 return; 618 case Arg: 619 if (UsesDotPrefix) 620 os << "."; 621 if (usesPositionalArg()) 622 os << "*" << getPositionalArgIndex() << "$"; 623 else 624 os << "*"; 625 break; 626 case Constant: 627 if (UsesDotPrefix) 628 os << "."; 629 os << amt; 630 break; 631 } 632} 633 634//===----------------------------------------------------------------------===// 635// Methods on FormatSpecifier. 636//===----------------------------------------------------------------------===// 637 638ArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const { 639 if (!CS.consumesDataArgument()) 640 return ArgTypeResult::Invalid(); 641 642 if (CS.isIntArg()) 643 switch (LM.getKind()) { 644 case LengthModifier::AsLongDouble: 645 return ArgTypeResult::Invalid(); 646 case LengthModifier::None: return Ctx.IntTy; 647 case LengthModifier::AsChar: return Ctx.SignedCharTy; 648 case LengthModifier::AsShort: return Ctx.ShortTy; 649 case LengthModifier::AsLong: return Ctx.LongTy; 650 case LengthModifier::AsLongLong: return Ctx.LongLongTy; 651 case LengthModifier::AsIntMax: 652 // FIXME: Return unknown for now. 653 return ArgTypeResult(); 654 case LengthModifier::AsSizeT: return Ctx.getSizeType(); 655 case LengthModifier::AsPtrDiff: return Ctx.getPointerDiffType(); 656 } 657 658 if (CS.isUIntArg()) 659 switch (LM.getKind()) { 660 case LengthModifier::AsLongDouble: 661 return ArgTypeResult::Invalid(); 662 case LengthModifier::None: return Ctx.UnsignedIntTy; 663 case LengthModifier::AsChar: return Ctx.UnsignedCharTy; 664 case LengthModifier::AsShort: return Ctx.UnsignedShortTy; 665 case LengthModifier::AsLong: return Ctx.UnsignedLongTy; 666 case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy; 667 case LengthModifier::AsIntMax: 668 // FIXME: Return unknown for now. 669 return ArgTypeResult(); 670 case LengthModifier::AsSizeT: 671 // FIXME: How to get the corresponding unsigned 672 // version of size_t? 673 return ArgTypeResult(); 674 case LengthModifier::AsPtrDiff: 675 // FIXME: How to get the corresponding unsigned 676 // version of ptrdiff_t? 677 return ArgTypeResult(); 678 } 679 680 if (CS.isDoubleArg()) { 681 if (LM.getKind() == LengthModifier::AsLongDouble) 682 return Ctx.LongDoubleTy; 683 return Ctx.DoubleTy; 684 } 685 686 switch (CS.getKind()) { 687 case ConversionSpecifier::CStrArg: 688 return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ? 689 ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy); 690 case ConversionSpecifier::UnicodeStrArg: 691 // FIXME: This appears to be Mac OS X specific. 692 return ArgTypeResult::WCStrTy; 693 case ConversionSpecifier::CArg: 694 return Ctx.WCharTy; 695 case ConversionSpecifier::VoidPtrArg: 696 return ArgTypeResult::CPointerTy; 697 default: 698 break; 699 } 700 701 // FIXME: Handle other cases. 702 return ArgTypeResult(); 703} 704 705bool FormatSpecifier::fixType(QualType QT) { 706 // Handle strings first (char *, wchar_t *) 707 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { 708 CS.setKind(ConversionSpecifier::CStrArg); 709 710 // Disable irrelevant flags 711 HasAlternativeForm = 0; 712 HasLeadingZeroes = 0; 713 714 // Set the long length modifier for wide characters 715 if (QT->getPointeeType()->isWideCharType()) 716 LM.setKind(LengthModifier::AsWideChar); 717 718 return true; 719 } 720 721 // We can only work with builtin types. 722 if (!QT->isBuiltinType()) 723 return false; 724 725 // Everything else should be a base type 726 const BuiltinType *BT = QT->getAs<BuiltinType>(); 727 728 // Set length modifier 729 switch (BT->getKind()) { 730 default: 731 // The rest of the conversions are either optional or for non-builtin types 732 LM.setKind(LengthModifier::None); 733 break; 734 735 case BuiltinType::WChar: 736 case BuiltinType::Long: 737 case BuiltinType::ULong: 738 LM.setKind(LengthModifier::AsLong); 739 break; 740 741 case BuiltinType::LongLong: 742 case BuiltinType::ULongLong: 743 LM.setKind(LengthModifier::AsLongLong); 744 break; 745 746 case BuiltinType::LongDouble: 747 LM.setKind(LengthModifier::AsLongDouble); 748 break; 749 } 750 751 // Set conversion specifier and disable any flags which do not apply to it. 752 if (QT->isAnyCharacterType()) { 753 CS.setKind(ConversionSpecifier::IntAsCharArg); 754 Precision.setHowSpecified(OptionalAmount::NotSpecified); 755 HasAlternativeForm = 0; 756 HasLeadingZeroes = 0; 757 HasPlusPrefix = 0; 758 } 759 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType 760 else if (QT->isRealFloatingType()) { 761 CS.setKind(ConversionSpecifier::fArg); 762 } 763 else if (QT->isPointerType()) { 764 CS.setKind(ConversionSpecifier::VoidPtrArg); 765 Precision.setHowSpecified(OptionalAmount::NotSpecified); 766 HasAlternativeForm = 0; 767 HasLeadingZeroes = 0; 768 HasPlusPrefix = 0; 769 } 770 else if (QT->isSignedIntegerType()) { 771 CS.setKind(ConversionSpecifier::dArg); 772 HasAlternativeForm = 0; 773 } 774 else if (QT->isUnsignedIntegerType()) { 775 CS.setKind(ConversionSpecifier::uArg); 776 HasAlternativeForm = 0; 777 HasPlusPrefix = 0; 778 } 779 else { 780 return false; 781 } 782 783 return true; 784} 785 786void FormatSpecifier::toString(llvm::raw_ostream &os) const { 787 // Whilst some features have no defined order, we are using the order 788 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) �7.19.6.1) 789 os << "%"; 790 791 // Positional args 792 if (usesPositionalArg()) { 793 os << getPositionalArgIndex() << "$"; 794 } 795 796 // Conversion flags 797 if (IsLeftJustified) os << "-"; 798 if (HasPlusPrefix) os << "+"; 799 if (HasSpacePrefix) os << " "; 800 if (HasAlternativeForm) os << "#"; 801 if (HasLeadingZeroes) os << "0"; 802 803 // Minimum field width 804 FieldWidth.toString(os); 805 // Precision 806 Precision.toString(os); 807 // Length modifier 808 os << LM.toString(); 809 // Conversion specifier 810 os << CS.toString(); 811} 812 813bool FormatSpecifier::hasValidPlusPrefix() const { 814 if (!HasPlusPrefix) 815 return true; 816 817 // The plus prefix only makes sense for signed conversions 818 switch (CS.getKind()) { 819 case ConversionSpecifier::dArg: 820 case ConversionSpecifier::iArg: 821 case ConversionSpecifier::fArg: 822 case ConversionSpecifier::FArg: 823 case ConversionSpecifier::eArg: 824 case ConversionSpecifier::EArg: 825 case ConversionSpecifier::gArg: 826 case ConversionSpecifier::GArg: 827 case ConversionSpecifier::aArg: 828 case ConversionSpecifier::AArg: 829 return true; 830 831 default: 832 return false; 833 } 834} 835 836bool FormatSpecifier::hasValidAlternativeForm() const { 837 if (!HasAlternativeForm) 838 return true; 839 840 // Alternate form flag only valid with the oxaAeEfFgG conversions 841 switch (CS.getKind()) { 842 case ConversionSpecifier::oArg: 843 case ConversionSpecifier::xArg: 844 case ConversionSpecifier::aArg: 845 case ConversionSpecifier::AArg: 846 case ConversionSpecifier::eArg: 847 case ConversionSpecifier::EArg: 848 case ConversionSpecifier::fArg: 849 case ConversionSpecifier::FArg: 850 case ConversionSpecifier::gArg: 851 case ConversionSpecifier::GArg: 852 return true; 853 854 default: 855 return false; 856 } 857} 858 859bool FormatSpecifier::hasValidLeadingZeros() const { 860 if (!HasLeadingZeroes) 861 return true; 862 863 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions 864 switch (CS.getKind()) { 865 case ConversionSpecifier::dArg: 866 case ConversionSpecifier::iArg: 867 case ConversionSpecifier::oArg: 868 case ConversionSpecifier::uArg: 869 case ConversionSpecifier::xArg: 870 case ConversionSpecifier::XArg: 871 case ConversionSpecifier::aArg: 872 case ConversionSpecifier::AArg: 873 case ConversionSpecifier::eArg: 874 case ConversionSpecifier::EArg: 875 case ConversionSpecifier::fArg: 876 case ConversionSpecifier::FArg: 877 case ConversionSpecifier::gArg: 878 case ConversionSpecifier::GArg: 879 return true; 880 881 default: 882 return false; 883 } 884} 885 886bool FormatSpecifier::hasValidSpacePrefix() const { 887 if (!HasSpacePrefix) 888 return true; 889 890 // The space prefix only makes sense for signed conversions 891 switch (CS.getKind()) { 892 case ConversionSpecifier::dArg: 893 case ConversionSpecifier::iArg: 894 case ConversionSpecifier::fArg: 895 case ConversionSpecifier::FArg: 896 case ConversionSpecifier::eArg: 897 case ConversionSpecifier::EArg: 898 case ConversionSpecifier::gArg: 899 case ConversionSpecifier::GArg: 900 case ConversionSpecifier::aArg: 901 case ConversionSpecifier::AArg: 902 return true; 903 904 default: 905 return false; 906 } 907} 908 909bool FormatSpecifier::hasValidLeftJustified() const { 910 if (!IsLeftJustified) 911 return true; 912 913 // The left justified flag is valid for all conversions except n 914 switch (CS.getKind()) { 915 case ConversionSpecifier::OutIntPtrArg: 916 return false; 917 918 default: 919 return true; 920 } 921} 922 923bool FormatSpecifier::hasValidLengthModifier() const { 924 switch (LM.getKind()) { 925 case LengthModifier::None: 926 return true; 927 928 // Handle most integer flags 929 case LengthModifier::AsChar: 930 case LengthModifier::AsShort: 931 case LengthModifier::AsLongLong: 932 case LengthModifier::AsIntMax: 933 case LengthModifier::AsSizeT: 934 case LengthModifier::AsPtrDiff: 935 switch (CS.getKind()) { 936 case ConversionSpecifier::dArg: 937 case ConversionSpecifier::iArg: 938 case ConversionSpecifier::oArg: 939 case ConversionSpecifier::uArg: 940 case ConversionSpecifier::xArg: 941 case ConversionSpecifier::XArg: 942 case ConversionSpecifier::OutIntPtrArg: 943 return true; 944 default: 945 return false; 946 } 947 948 // Handle 'l' flag 949 case LengthModifier::AsLong: 950 switch (CS.getKind()) { 951 case ConversionSpecifier::dArg: 952 case ConversionSpecifier::iArg: 953 case ConversionSpecifier::oArg: 954 case ConversionSpecifier::uArg: 955 case ConversionSpecifier::xArg: 956 case ConversionSpecifier::XArg: 957 case ConversionSpecifier::aArg: 958 case ConversionSpecifier::AArg: 959 case ConversionSpecifier::fArg: 960 case ConversionSpecifier::FArg: 961 case ConversionSpecifier::eArg: 962 case ConversionSpecifier::EArg: 963 case ConversionSpecifier::gArg: 964 case ConversionSpecifier::GArg: 965 case ConversionSpecifier::OutIntPtrArg: 966 case ConversionSpecifier::IntAsCharArg: 967 case ConversionSpecifier::CStrArg: 968 return true; 969 default: 970 return false; 971 } 972 973 case LengthModifier::AsLongDouble: 974 switch (CS.getKind()) { 975 case ConversionSpecifier::aArg: 976 case ConversionSpecifier::AArg: 977 case ConversionSpecifier::fArg: 978 case ConversionSpecifier::FArg: 979 case ConversionSpecifier::eArg: 980 case ConversionSpecifier::EArg: 981 case ConversionSpecifier::gArg: 982 case ConversionSpecifier::GArg: 983 return true; 984 default: 985 return false; 986 } 987 } 988 return false; 989} 990 991bool FormatSpecifier::hasValidPrecision() const { 992 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified) 993 return true; 994 995 // Precision is only valid with the diouxXaAeEfFgGs conversions 996 switch (CS.getKind()) { 997 case ConversionSpecifier::dArg: 998 case ConversionSpecifier::iArg: 999 case ConversionSpecifier::oArg: 1000 case ConversionSpecifier::uArg: 1001 case ConversionSpecifier::xArg: 1002 case ConversionSpecifier::XArg: 1003 case ConversionSpecifier::aArg: 1004 case ConversionSpecifier::AArg: 1005 case ConversionSpecifier::eArg: 1006 case ConversionSpecifier::EArg: 1007 case ConversionSpecifier::fArg: 1008 case ConversionSpecifier::FArg: 1009 case ConversionSpecifier::gArg: 1010 case ConversionSpecifier::GArg: 1011 case ConversionSpecifier::CStrArg: 1012 return true; 1013 1014 default: 1015 return false; 1016 } 1017} 1018bool FormatSpecifier::hasValidFieldWidth() const { 1019 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified) 1020 return true; 1021 1022 // The field width is valid for all conversions except n 1023 switch (CS.getKind()) { 1024 case ConversionSpecifier::OutIntPtrArg: 1025 return false; 1026 1027 default: 1028 return true; 1029 } 1030} 1031