1 // FormatString.cpp - Common stuff for handling printf/scanf formats -*- 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 // Shared details for processing format strings of printf and scanf 11 // (and friends). 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "FormatStringParsing.h" 16 #include "clang/Basic/LangOptions.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::FormatSpecifier; 22 using clang::analyze_format_string::LengthModifier; 23 using clang::analyze_format_string::OptionalAmount; 24 using clang::analyze_format_string::PositionContext; 25 using clang::analyze_format_string::ConversionSpecifier; 26 using namespace clang; 27 28 // Key function to FormatStringHandler. 29 FormatStringHandler::~FormatStringHandler() {} 30 31 //===----------------------------------------------------------------------===// 32 // Functions for parsing format strings components in both printf and 33 // scanf format strings. 34 //===----------------------------------------------------------------------===// 35 36 OptionalAmount 37 clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) { 38 const char *I = Beg; 39 UpdateOnReturn <const char*> UpdateBeg(Beg, I); 40 41 unsigned accumulator = 0; 42 bool hasDigits = false; 43 44 for ( ; I != E; ++I) { 45 char c = *I; 46 if (c >= '0' && c <= '9') { 47 hasDigits = true; 48 accumulator = (accumulator * 10) + (c - '0'); 49 continue; 50 } 51 52 if (hasDigits) 53 return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg, 54 false); 55 56 break; 57 } 58 59 return OptionalAmount(); 60 } 61 62 OptionalAmount 63 clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg, 64 const char *E, 65 unsigned &argIndex) { 66 if (*Beg == '*') { 67 ++Beg; 68 return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false); 69 } 70 71 return ParseAmount(Beg, E); 72 } 73 74 OptionalAmount 75 clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H, 76 const char *Start, 77 const char *&Beg, 78 const char *E, 79 PositionContext p) { 80 if (*Beg == '*') { 81 const char *I = Beg + 1; 82 const OptionalAmount &Amt = ParseAmount(I, E); 83 84 if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) { 85 H.HandleInvalidPosition(Beg, I - Beg, p); 86 return OptionalAmount(false); 87 } 88 89 if (I == E) { 90 // No more characters left? 91 H.HandleIncompleteSpecifier(Start, E - Start); 92 return OptionalAmount(false); 93 } 94 95 assert(Amt.getHowSpecified() == OptionalAmount::Constant); 96 97 if (*I == '$') { 98 // Handle positional arguments 99 100 // Special case: '*0$', since this is an easy mistake. 101 if (Amt.getConstantAmount() == 0) { 102 H.HandleZeroPosition(Beg, I - Beg + 1); 103 return OptionalAmount(false); 104 } 105 106 const char *Tmp = Beg; 107 Beg = ++I; 108 109 return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1, 110 Tmp, 0, true); 111 } 112 113 H.HandleInvalidPosition(Beg, I - Beg, p); 114 return OptionalAmount(false); 115 } 116 117 return ParseAmount(Beg, E); 118 } 119 120 121 bool 122 clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H, 123 FormatSpecifier &CS, 124 const char *Start, 125 const char *&Beg, const char *E, 126 unsigned *argIndex) { 127 // FIXME: Support negative field widths. 128 if (argIndex) { 129 CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex)); 130 } 131 else { 132 const OptionalAmount Amt = 133 ParsePositionAmount(H, Start, Beg, E, 134 analyze_format_string::FieldWidthPos); 135 136 if (Amt.isInvalid()) 137 return true; 138 CS.setFieldWidth(Amt); 139 } 140 return false; 141 } 142 143 bool 144 clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H, 145 FormatSpecifier &FS, 146 const char *Start, 147 const char *&Beg, 148 const char *E) { 149 const char *I = Beg; 150 151 const OptionalAmount &Amt = ParseAmount(I, E); 152 153 if (I == E) { 154 // No more characters left? 155 H.HandleIncompleteSpecifier(Start, E - Start); 156 return true; 157 } 158 159 if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') { 160 // Warn that positional arguments are non-standard. 161 H.HandlePosition(Start, I - Start); 162 163 // Special case: '%0$', since this is an easy mistake. 164 if (Amt.getConstantAmount() == 0) { 165 H.HandleZeroPosition(Start, I - Start); 166 return true; 167 } 168 169 FS.setArgIndex(Amt.getConstantAmount() - 1); 170 FS.setUsesPositionalArg(); 171 // Update the caller's pointer if we decided to consume 172 // these characters. 173 Beg = I; 174 return false; 175 } 176 177 return false; 178 } 179 180 bool 181 clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, 182 const char *&I, 183 const char *E, 184 const LangOptions &LO, 185 bool IsScanf) { 186 LengthModifier::Kind lmKind = LengthModifier::None; 187 const char *lmPosition = I; 188 switch (*I) { 189 default: 190 return false; 191 case 'h': 192 ++I; 193 lmKind = (I != E && *I == 'h') ? (++I, LengthModifier::AsChar) 194 : LengthModifier::AsShort; 195 break; 196 case 'l': 197 ++I; 198 lmKind = (I != E && *I == 'l') ? (++I, LengthModifier::AsLongLong) 199 : LengthModifier::AsLong; 200 break; 201 case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; 202 case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; 203 case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; 204 case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; 205 case 'q': lmKind = LengthModifier::AsQuad; ++I; break; 206 case 'a': 207 if (IsScanf && !LO.C99 && !LO.CPlusPlus11) { 208 // For scanf in C90, look at the next character to see if this should 209 // be parsed as the GNU extension 'a' length modifier. If not, this 210 // will be parsed as a conversion specifier. 211 ++I; 212 if (I != E && (*I == 's' || *I == 'S' || *I == '[')) { 213 lmKind = LengthModifier::AsAllocate; 214 break; 215 } 216 --I; 217 } 218 return false; 219 case 'm': 220 if (IsScanf) { 221 lmKind = LengthModifier::AsMAllocate; 222 ++I; 223 break; 224 } 225 return false; 226 } 227 LengthModifier lm(lmPosition, lmKind); 228 FS.setLengthModifier(lm); 229 return true; 230 } 231 232 //===----------------------------------------------------------------------===// 233 // Methods on ArgType. 234 //===----------------------------------------------------------------------===// 235 236 bool ArgType::matchesType(ASTContext &C, QualType argTy) const { 237 if (Ptr) { 238 // It has to be a pointer. 239 const PointerType *PT = argTy->getAs<PointerType>(); 240 if (!PT) 241 return false; 242 243 // We cannot write through a const qualified pointer. 244 if (PT->getPointeeType().isConstQualified()) 245 return false; 246 247 argTy = PT->getPointeeType(); 248 } 249 250 switch (K) { 251 case InvalidTy: 252 llvm_unreachable("ArgType must be valid"); 253 254 case UnknownTy: 255 return true; 256 257 case AnyCharTy: { 258 if (const EnumType *ETy = argTy->getAs<EnumType>()) 259 argTy = ETy->getDecl()->getIntegerType(); 260 261 if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) 262 switch (BT->getKind()) { 263 default: 264 break; 265 case BuiltinType::Char_S: 266 case BuiltinType::SChar: 267 case BuiltinType::UChar: 268 case BuiltinType::Char_U: 269 return true; 270 } 271 return false; 272 } 273 274 case SpecificTy: { 275 if (const EnumType *ETy = argTy->getAs<EnumType>()) 276 argTy = ETy->getDecl()->getIntegerType(); 277 argTy = C.getCanonicalType(argTy).getUnqualifiedType(); 278 279 if (T == argTy) 280 return true; 281 // Check for "compatible types". 282 if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) 283 switch (BT->getKind()) { 284 default: 285 break; 286 case BuiltinType::Char_S: 287 case BuiltinType::SChar: 288 case BuiltinType::Char_U: 289 case BuiltinType::UChar: 290 return T == C.UnsignedCharTy || T == C.SignedCharTy; 291 case BuiltinType::Short: 292 return T == C.UnsignedShortTy; 293 case BuiltinType::UShort: 294 return T == C.ShortTy; 295 case BuiltinType::Int: 296 return T == C.UnsignedIntTy; 297 case BuiltinType::UInt: 298 return T == C.IntTy; 299 case BuiltinType::Long: 300 return T == C.UnsignedLongTy; 301 case BuiltinType::ULong: 302 return T == C.LongTy; 303 case BuiltinType::LongLong: 304 return T == C.UnsignedLongLongTy; 305 case BuiltinType::ULongLong: 306 return T == C.LongLongTy; 307 } 308 return false; 309 } 310 311 case CStrTy: { 312 const PointerType *PT = argTy->getAs<PointerType>(); 313 if (!PT) 314 return false; 315 QualType pointeeTy = PT->getPointeeType(); 316 if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) 317 switch (BT->getKind()) { 318 case BuiltinType::Void: 319 case BuiltinType::Char_U: 320 case BuiltinType::UChar: 321 case BuiltinType::Char_S: 322 case BuiltinType::SChar: 323 return true; 324 default: 325 break; 326 } 327 328 return false; 329 } 330 331 case WCStrTy: { 332 const PointerType *PT = argTy->getAs<PointerType>(); 333 if (!PT) 334 return false; 335 QualType pointeeTy = 336 C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); 337 return pointeeTy == C.getWideCharType(); 338 } 339 340 case WIntTy: { 341 342 QualType PromoArg = 343 argTy->isPromotableIntegerType() 344 ? C.getPromotedIntegerType(argTy) : argTy; 345 346 QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType(); 347 PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); 348 349 // If the promoted argument is the corresponding signed type of the 350 // wint_t type, then it should match. 351 if (PromoArg->hasSignedIntegerRepresentation() && 352 C.getCorrespondingUnsignedType(PromoArg) == WInt) 353 return true; 354 355 return WInt == PromoArg; 356 } 357 358 case CPointerTy: 359 return argTy->isPointerType() || argTy->isObjCObjectPointerType() || 360 argTy->isBlockPointerType() || argTy->isNullPtrType(); 361 362 case ObjCPointerTy: { 363 if (argTy->getAs<ObjCObjectPointerType>() || 364 argTy->getAs<BlockPointerType>()) 365 return true; 366 367 // Handle implicit toll-free bridging. 368 if (const PointerType *PT = argTy->getAs<PointerType>()) { 369 // Things such as CFTypeRef are really just opaque pointers 370 // to C structs representing CF types that can often be bridged 371 // to Objective-C objects. Since the compiler doesn't know which 372 // structs can be toll-free bridged, we just accept them all. 373 QualType pointee = PT->getPointeeType(); 374 if (pointee->getAsStructureType() || pointee->isVoidType()) 375 return true; 376 } 377 return false; 378 } 379 } 380 381 llvm_unreachable("Invalid ArgType Kind!"); 382 } 383 384 QualType ArgType::getRepresentativeType(ASTContext &C) const { 385 QualType Res; 386 switch (K) { 387 case InvalidTy: 388 llvm_unreachable("No representative type for Invalid ArgType"); 389 case UnknownTy: 390 llvm_unreachable("No representative type for Unknown ArgType"); 391 case AnyCharTy: 392 Res = C.CharTy; 393 break; 394 case SpecificTy: 395 Res = T; 396 break; 397 case CStrTy: 398 Res = C.getPointerType(C.CharTy); 399 break; 400 case WCStrTy: 401 Res = C.getPointerType(C.getWideCharType()); 402 break; 403 case ObjCPointerTy: 404 Res = C.ObjCBuiltinIdTy; 405 break; 406 case CPointerTy: 407 Res = C.VoidPtrTy; 408 break; 409 case WIntTy: { 410 Res = C.getWIntType(); 411 break; 412 } 413 } 414 415 if (Ptr) 416 Res = C.getPointerType(Res); 417 return Res; 418 } 419 420 std::string ArgType::getRepresentativeTypeName(ASTContext &C) const { 421 std::string S = getRepresentativeType(C).getAsString(); 422 423 std::string Alias; 424 if (Name) { 425 // Use a specific name for this type, e.g. "size_t". 426 Alias = Name; 427 if (Ptr) { 428 // If ArgType is actually a pointer to T, append an asterisk. 429 Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *"; 430 } 431 // If Alias is the same as the underlying type, e.g. wchar_t, then drop it. 432 if (S == Alias) 433 Alias.clear(); 434 } 435 436 if (!Alias.empty()) 437 return std::string("'") + Alias + "' (aka '" + S + "')"; 438 return std::string("'") + S + "'"; 439 } 440 441 442 //===----------------------------------------------------------------------===// 443 // Methods on OptionalAmount. 444 //===----------------------------------------------------------------------===// 445 446 ArgType 447 analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const { 448 return Ctx.IntTy; 449 } 450 451 //===----------------------------------------------------------------------===// 452 // Methods on LengthModifier. 453 //===----------------------------------------------------------------------===// 454 455 const char * 456 analyze_format_string::LengthModifier::toString() const { 457 switch (kind) { 458 case AsChar: 459 return "hh"; 460 case AsShort: 461 return "h"; 462 case AsLong: // or AsWideChar 463 return "l"; 464 case AsLongLong: 465 return "ll"; 466 case AsQuad: 467 return "q"; 468 case AsIntMax: 469 return "j"; 470 case AsSizeT: 471 return "z"; 472 case AsPtrDiff: 473 return "t"; 474 case AsLongDouble: 475 return "L"; 476 case AsAllocate: 477 return "a"; 478 case AsMAllocate: 479 return "m"; 480 case None: 481 return ""; 482 } 483 return NULL; 484 } 485 486 //===----------------------------------------------------------------------===// 487 // Methods on ConversionSpecifier. 488 //===----------------------------------------------------------------------===// 489 490 const char *ConversionSpecifier::toString() const { 491 switch (kind) { 492 case dArg: return "d"; 493 case DArg: return "D"; 494 case iArg: return "i"; 495 case oArg: return "o"; 496 case OArg: return "O"; 497 case uArg: return "u"; 498 case UArg: return "U"; 499 case xArg: return "x"; 500 case XArg: return "X"; 501 case fArg: return "f"; 502 case FArg: return "F"; 503 case eArg: return "e"; 504 case EArg: return "E"; 505 case gArg: return "g"; 506 case GArg: return "G"; 507 case aArg: return "a"; 508 case AArg: return "A"; 509 case cArg: return "c"; 510 case sArg: return "s"; 511 case pArg: return "p"; 512 case nArg: return "n"; 513 case PercentArg: return "%"; 514 case ScanListArg: return "["; 515 case InvalidSpecifier: return NULL; 516 517 // MacOS X unicode extensions. 518 case CArg: return "C"; 519 case SArg: return "S"; 520 521 // Objective-C specific specifiers. 522 case ObjCObjArg: return "@"; 523 524 // GlibC specific specifiers. 525 case PrintErrno: return "m"; 526 } 527 return NULL; 528 } 529 530 Optional<ConversionSpecifier> 531 ConversionSpecifier::getStandardSpecifier() const { 532 ConversionSpecifier::Kind NewKind; 533 534 switch (getKind()) { 535 default: 536 return None; 537 case DArg: 538 NewKind = dArg; 539 break; 540 case UArg: 541 NewKind = uArg; 542 break; 543 case OArg: 544 NewKind = oArg; 545 break; 546 } 547 548 ConversionSpecifier FixedCS(*this); 549 FixedCS.setKind(NewKind); 550 return FixedCS; 551 } 552 553 //===----------------------------------------------------------------------===// 554 // Methods on OptionalAmount. 555 //===----------------------------------------------------------------------===// 556 557 void OptionalAmount::toString(raw_ostream &os) const { 558 switch (hs) { 559 case Invalid: 560 case NotSpecified: 561 return; 562 case Arg: 563 if (UsesDotPrefix) 564 os << "."; 565 if (usesPositionalArg()) 566 os << "*" << getPositionalArgIndex() << "$"; 567 else 568 os << "*"; 569 break; 570 case Constant: 571 if (UsesDotPrefix) 572 os << "."; 573 os << amt; 574 break; 575 } 576 } 577 578 bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const { 579 switch (LM.getKind()) { 580 case LengthModifier::None: 581 return true; 582 583 // Handle most integer flags 584 case LengthModifier::AsChar: 585 case LengthModifier::AsShort: 586 case LengthModifier::AsLongLong: 587 case LengthModifier::AsQuad: 588 case LengthModifier::AsIntMax: 589 case LengthModifier::AsSizeT: 590 case LengthModifier::AsPtrDiff: 591 switch (CS.getKind()) { 592 case ConversionSpecifier::dArg: 593 case ConversionSpecifier::DArg: 594 case ConversionSpecifier::iArg: 595 case ConversionSpecifier::oArg: 596 case ConversionSpecifier::OArg: 597 case ConversionSpecifier::uArg: 598 case ConversionSpecifier::UArg: 599 case ConversionSpecifier::xArg: 600 case ConversionSpecifier::XArg: 601 case ConversionSpecifier::nArg: 602 return true; 603 default: 604 return false; 605 } 606 607 // Handle 'l' flag 608 case LengthModifier::AsLong: 609 switch (CS.getKind()) { 610 case ConversionSpecifier::dArg: 611 case ConversionSpecifier::DArg: 612 case ConversionSpecifier::iArg: 613 case ConversionSpecifier::oArg: 614 case ConversionSpecifier::OArg: 615 case ConversionSpecifier::uArg: 616 case ConversionSpecifier::UArg: 617 case ConversionSpecifier::xArg: 618 case ConversionSpecifier::XArg: 619 case ConversionSpecifier::aArg: 620 case ConversionSpecifier::AArg: 621 case ConversionSpecifier::fArg: 622 case ConversionSpecifier::FArg: 623 case ConversionSpecifier::eArg: 624 case ConversionSpecifier::EArg: 625 case ConversionSpecifier::gArg: 626 case ConversionSpecifier::GArg: 627 case ConversionSpecifier::nArg: 628 case ConversionSpecifier::cArg: 629 case ConversionSpecifier::sArg: 630 case ConversionSpecifier::ScanListArg: 631 return true; 632 default: 633 return false; 634 } 635 636 case LengthModifier::AsLongDouble: 637 switch (CS.getKind()) { 638 case ConversionSpecifier::aArg: 639 case ConversionSpecifier::AArg: 640 case ConversionSpecifier::fArg: 641 case ConversionSpecifier::FArg: 642 case ConversionSpecifier::eArg: 643 case ConversionSpecifier::EArg: 644 case ConversionSpecifier::gArg: 645 case ConversionSpecifier::GArg: 646 return true; 647 // GNU libc extension. 648 case ConversionSpecifier::dArg: 649 case ConversionSpecifier::iArg: 650 case ConversionSpecifier::oArg: 651 case ConversionSpecifier::uArg: 652 case ConversionSpecifier::xArg: 653 case ConversionSpecifier::XArg: 654 return !Target.getTriple().isOSDarwin() && 655 !Target.getTriple().isOSWindows(); 656 default: 657 return false; 658 } 659 660 case LengthModifier::AsAllocate: 661 switch (CS.getKind()) { 662 case ConversionSpecifier::sArg: 663 case ConversionSpecifier::SArg: 664 case ConversionSpecifier::ScanListArg: 665 return true; 666 default: 667 return false; 668 } 669 670 case LengthModifier::AsMAllocate: 671 switch (CS.getKind()) { 672 case ConversionSpecifier::cArg: 673 case ConversionSpecifier::CArg: 674 case ConversionSpecifier::sArg: 675 case ConversionSpecifier::SArg: 676 case ConversionSpecifier::ScanListArg: 677 return true; 678 default: 679 return false; 680 } 681 } 682 llvm_unreachable("Invalid LengthModifier Kind!"); 683 } 684 685 bool FormatSpecifier::hasStandardLengthModifier() const { 686 switch (LM.getKind()) { 687 case LengthModifier::None: 688 case LengthModifier::AsChar: 689 case LengthModifier::AsShort: 690 case LengthModifier::AsLong: 691 case LengthModifier::AsLongLong: 692 case LengthModifier::AsIntMax: 693 case LengthModifier::AsSizeT: 694 case LengthModifier::AsPtrDiff: 695 case LengthModifier::AsLongDouble: 696 return true; 697 case LengthModifier::AsAllocate: 698 case LengthModifier::AsMAllocate: 699 case LengthModifier::AsQuad: 700 return false; 701 } 702 llvm_unreachable("Invalid LengthModifier Kind!"); 703 } 704 705 bool FormatSpecifier::hasStandardConversionSpecifier(const LangOptions &LangOpt) const { 706 switch (CS.getKind()) { 707 case ConversionSpecifier::cArg: 708 case ConversionSpecifier::dArg: 709 case ConversionSpecifier::iArg: 710 case ConversionSpecifier::oArg: 711 case ConversionSpecifier::uArg: 712 case ConversionSpecifier::xArg: 713 case ConversionSpecifier::XArg: 714 case ConversionSpecifier::fArg: 715 case ConversionSpecifier::FArg: 716 case ConversionSpecifier::eArg: 717 case ConversionSpecifier::EArg: 718 case ConversionSpecifier::gArg: 719 case ConversionSpecifier::GArg: 720 case ConversionSpecifier::aArg: 721 case ConversionSpecifier::AArg: 722 case ConversionSpecifier::sArg: 723 case ConversionSpecifier::pArg: 724 case ConversionSpecifier::nArg: 725 case ConversionSpecifier::ObjCObjArg: 726 case ConversionSpecifier::ScanListArg: 727 case ConversionSpecifier::PercentArg: 728 return true; 729 case ConversionSpecifier::CArg: 730 case ConversionSpecifier::SArg: 731 return LangOpt.ObjC1 || LangOpt.ObjC2; 732 case ConversionSpecifier::InvalidSpecifier: 733 case ConversionSpecifier::PrintErrno: 734 case ConversionSpecifier::DArg: 735 case ConversionSpecifier::OArg: 736 case ConversionSpecifier::UArg: 737 return false; 738 } 739 llvm_unreachable("Invalid ConversionSpecifier Kind!"); 740 } 741 742 bool FormatSpecifier::hasStandardLengthConversionCombination() const { 743 if (LM.getKind() == LengthModifier::AsLongDouble) { 744 switch(CS.getKind()) { 745 case ConversionSpecifier::dArg: 746 case ConversionSpecifier::iArg: 747 case ConversionSpecifier::oArg: 748 case ConversionSpecifier::uArg: 749 case ConversionSpecifier::xArg: 750 case ConversionSpecifier::XArg: 751 return false; 752 default: 753 return true; 754 } 755 } 756 return true; 757 } 758 759 Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const { 760 if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) { 761 if (LM.getKind() == LengthModifier::AsLongDouble || 762 LM.getKind() == LengthModifier::AsQuad) { 763 LengthModifier FixedLM(LM); 764 FixedLM.setKind(LengthModifier::AsLongLong); 765 return FixedLM; 766 } 767 } 768 769 return None; 770 } 771 772 bool FormatSpecifier::namedTypeToLengthModifier(QualType QT, 773 LengthModifier &LM) { 774 assert(isa<TypedefType>(QT) && "Expected a TypedefType"); 775 const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl(); 776 777 for (;;) { 778 const IdentifierInfo *Identifier = Typedef->getIdentifier(); 779 if (Identifier->getName() == "size_t") { 780 LM.setKind(LengthModifier::AsSizeT); 781 return true; 782 } else if (Identifier->getName() == "ssize_t") { 783 // Not C99, but common in Unix. 784 LM.setKind(LengthModifier::AsSizeT); 785 return true; 786 } else if (Identifier->getName() == "intmax_t") { 787 LM.setKind(LengthModifier::AsIntMax); 788 return true; 789 } else if (Identifier->getName() == "uintmax_t") { 790 LM.setKind(LengthModifier::AsIntMax); 791 return true; 792 } else if (Identifier->getName() == "ptrdiff_t") { 793 LM.setKind(LengthModifier::AsPtrDiff); 794 return true; 795 } 796 797 QualType T = Typedef->getUnderlyingType(); 798 if (!isa<TypedefType>(T)) 799 break; 800 801 Typedef = cast<TypedefType>(T)->getDecl(); 802 } 803 return false; 804 } 805