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