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