Home | History | Annotate | Download | only in Analysis
      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.CPlusPlus0x) {
    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.getWCharType();
    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.getWCharType());
    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 iArg: return "i";
    494   case oArg: return "o";
    495   case uArg: return "u";
    496   case xArg: return "x";
    497   case XArg: return "X";
    498   case fArg: return "f";
    499   case FArg: return "F";
    500   case eArg: return "e";
    501   case EArg: return "E";
    502   case gArg: return "g";
    503   case GArg: return "G";
    504   case aArg: return "a";
    505   case AArg: return "A";
    506   case cArg: return "c";
    507   case sArg: return "s";
    508   case pArg: return "p";
    509   case nArg: return "n";
    510   case PercentArg:  return "%";
    511   case ScanListArg: return "[";
    512   case InvalidSpecifier: return NULL;
    513 
    514   // MacOS X unicode extensions.
    515   case CArg: return "C";
    516   case SArg: return "S";
    517 
    518   // Objective-C specific specifiers.
    519   case ObjCObjArg: return "@";
    520 
    521   // GlibC specific specifiers.
    522   case PrintErrno: return "m";
    523   }
    524   return NULL;
    525 }
    526 
    527 //===----------------------------------------------------------------------===//
    528 // Methods on OptionalAmount.
    529 //===----------------------------------------------------------------------===//
    530 
    531 void OptionalAmount::toString(raw_ostream &os) const {
    532   switch (hs) {
    533   case Invalid:
    534   case NotSpecified:
    535     return;
    536   case Arg:
    537     if (UsesDotPrefix)
    538         os << ".";
    539     if (usesPositionalArg())
    540       os << "*" << getPositionalArgIndex() << "$";
    541     else
    542       os << "*";
    543     break;
    544   case Constant:
    545     if (UsesDotPrefix)
    546         os << ".";
    547     os << amt;
    548     break;
    549   }
    550 }
    551 
    552 bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {
    553   switch (LM.getKind()) {
    554     case LengthModifier::None:
    555       return true;
    556 
    557     // Handle most integer flags
    558     case LengthModifier::AsChar:
    559     case LengthModifier::AsShort:
    560     case LengthModifier::AsLongLong:
    561     case LengthModifier::AsQuad:
    562     case LengthModifier::AsIntMax:
    563     case LengthModifier::AsSizeT:
    564     case LengthModifier::AsPtrDiff:
    565       switch (CS.getKind()) {
    566         case ConversionSpecifier::dArg:
    567         case ConversionSpecifier::iArg:
    568         case ConversionSpecifier::oArg:
    569         case ConversionSpecifier::uArg:
    570         case ConversionSpecifier::xArg:
    571         case ConversionSpecifier::XArg:
    572         case ConversionSpecifier::nArg:
    573           return true;
    574         default:
    575           return false;
    576       }
    577 
    578     // Handle 'l' flag
    579     case LengthModifier::AsLong:
    580       switch (CS.getKind()) {
    581         case ConversionSpecifier::dArg:
    582         case ConversionSpecifier::iArg:
    583         case ConversionSpecifier::oArg:
    584         case ConversionSpecifier::uArg:
    585         case ConversionSpecifier::xArg:
    586         case ConversionSpecifier::XArg:
    587         case ConversionSpecifier::aArg:
    588         case ConversionSpecifier::AArg:
    589         case ConversionSpecifier::fArg:
    590         case ConversionSpecifier::FArg:
    591         case ConversionSpecifier::eArg:
    592         case ConversionSpecifier::EArg:
    593         case ConversionSpecifier::gArg:
    594         case ConversionSpecifier::GArg:
    595         case ConversionSpecifier::nArg:
    596         case ConversionSpecifier::cArg:
    597         case ConversionSpecifier::sArg:
    598         case ConversionSpecifier::ScanListArg:
    599           return true;
    600         default:
    601           return false;
    602       }
    603 
    604     case LengthModifier::AsLongDouble:
    605       switch (CS.getKind()) {
    606         case ConversionSpecifier::aArg:
    607         case ConversionSpecifier::AArg:
    608         case ConversionSpecifier::fArg:
    609         case ConversionSpecifier::FArg:
    610         case ConversionSpecifier::eArg:
    611         case ConversionSpecifier::EArg:
    612         case ConversionSpecifier::gArg:
    613         case ConversionSpecifier::GArg:
    614           return true;
    615         // GNU libc extension.
    616         case ConversionSpecifier::dArg:
    617         case ConversionSpecifier::iArg:
    618         case ConversionSpecifier::oArg:
    619         case ConversionSpecifier::uArg:
    620         case ConversionSpecifier::xArg:
    621         case ConversionSpecifier::XArg:
    622           return !Target.getTriple().isOSDarwin() &&
    623                  !Target.getTriple().isOSWindows();
    624         default:
    625           return false;
    626       }
    627 
    628     case LengthModifier::AsAllocate:
    629       switch (CS.getKind()) {
    630         case ConversionSpecifier::sArg:
    631         case ConversionSpecifier::SArg:
    632         case ConversionSpecifier::ScanListArg:
    633           return true;
    634         default:
    635           return false;
    636       }
    637 
    638     case LengthModifier::AsMAllocate:
    639       switch (CS.getKind()) {
    640         case ConversionSpecifier::cArg:
    641         case ConversionSpecifier::CArg:
    642         case ConversionSpecifier::sArg:
    643         case ConversionSpecifier::SArg:
    644         case ConversionSpecifier::ScanListArg:
    645           return true;
    646         default:
    647           return false;
    648       }
    649   }
    650   llvm_unreachable("Invalid LengthModifier Kind!");
    651 }
    652 
    653 bool FormatSpecifier::hasStandardLengthModifier() const {
    654   switch (LM.getKind()) {
    655     case LengthModifier::None:
    656     case LengthModifier::AsChar:
    657     case LengthModifier::AsShort:
    658     case LengthModifier::AsLong:
    659     case LengthModifier::AsLongLong:
    660     case LengthModifier::AsIntMax:
    661     case LengthModifier::AsSizeT:
    662     case LengthModifier::AsPtrDiff:
    663     case LengthModifier::AsLongDouble:
    664       return true;
    665     case LengthModifier::AsAllocate:
    666     case LengthModifier::AsMAllocate:
    667     case LengthModifier::AsQuad:
    668       return false;
    669   }
    670   llvm_unreachable("Invalid LengthModifier Kind!");
    671 }
    672 
    673 bool FormatSpecifier::hasStandardConversionSpecifier(const LangOptions &LangOpt) const {
    674   switch (CS.getKind()) {
    675     case ConversionSpecifier::cArg:
    676     case ConversionSpecifier::dArg:
    677     case ConversionSpecifier::iArg:
    678     case ConversionSpecifier::oArg:
    679     case ConversionSpecifier::uArg:
    680     case ConversionSpecifier::xArg:
    681     case ConversionSpecifier::XArg:
    682     case ConversionSpecifier::fArg:
    683     case ConversionSpecifier::FArg:
    684     case ConversionSpecifier::eArg:
    685     case ConversionSpecifier::EArg:
    686     case ConversionSpecifier::gArg:
    687     case ConversionSpecifier::GArg:
    688     case ConversionSpecifier::aArg:
    689     case ConversionSpecifier::AArg:
    690     case ConversionSpecifier::sArg:
    691     case ConversionSpecifier::pArg:
    692     case ConversionSpecifier::nArg:
    693     case ConversionSpecifier::ObjCObjArg:
    694     case ConversionSpecifier::ScanListArg:
    695     case ConversionSpecifier::PercentArg:
    696       return true;
    697     case ConversionSpecifier::CArg:
    698     case ConversionSpecifier::SArg:
    699       return LangOpt.ObjC1 || LangOpt.ObjC2;
    700     case ConversionSpecifier::InvalidSpecifier:
    701     case ConversionSpecifier::PrintErrno:
    702       return false;
    703   }
    704   llvm_unreachable("Invalid ConversionSpecifier Kind!");
    705 }
    706 
    707 bool FormatSpecifier::hasStandardLengthConversionCombination() const {
    708   if (LM.getKind() == LengthModifier::AsLongDouble) {
    709     switch(CS.getKind()) {
    710         case ConversionSpecifier::dArg:
    711         case ConversionSpecifier::iArg:
    712         case ConversionSpecifier::oArg:
    713         case ConversionSpecifier::uArg:
    714         case ConversionSpecifier::xArg:
    715         case ConversionSpecifier::XArg:
    716           return false;
    717         default:
    718           return true;
    719     }
    720   }
    721   return true;
    722 }
    723 
    724 llvm::Optional<LengthModifier>
    725 FormatSpecifier::getCorrectedLengthModifier() const {
    726   if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
    727     if (LM.getKind() == LengthModifier::AsLongDouble ||
    728         LM.getKind() == LengthModifier::AsQuad) {
    729       LengthModifier FixedLM(LM);
    730       FixedLM.setKind(LengthModifier::AsLongLong);
    731       return FixedLM;
    732     }
    733   }
    734 
    735   return llvm::Optional<LengthModifier>();
    736 }
    737 
    738 bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,
    739                                                 LengthModifier &LM) {
    740   assert(isa<TypedefType>(QT) && "Expected a TypedefType");
    741   const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();
    742 
    743   for (;;) {
    744     const IdentifierInfo *Identifier = Typedef->getIdentifier();
    745     if (Identifier->getName() == "size_t") {
    746       LM.setKind(LengthModifier::AsSizeT);
    747       return true;
    748     } else if (Identifier->getName() == "ssize_t") {
    749       // Not C99, but common in Unix.
    750       LM.setKind(LengthModifier::AsSizeT);
    751       return true;
    752     } else if (Identifier->getName() == "intmax_t") {
    753       LM.setKind(LengthModifier::AsIntMax);
    754       return true;
    755     } else if (Identifier->getName() == "uintmax_t") {
    756       LM.setKind(LengthModifier::AsIntMax);
    757       return true;
    758     } else if (Identifier->getName() == "ptrdiff_t") {
    759       LM.setKind(LengthModifier::AsPtrDiff);
    760       return true;
    761     }
    762 
    763     QualType T = Typedef->getUnderlyingType();
    764     if (!isa<TypedefType>(T))
    765       break;
    766 
    767     Typedef = cast<TypedefType>(T)->getDecl();
    768   }
    769   return false;
    770 }
    771