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 = nullptr;
     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() ? nullptr : &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() ? nullptr : &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:
    282         return Ctx.IntTy;
    283       case LengthModifier::AsInt32:
    284         return ArgType(Ctx.IntTy, "__int32");
    285       case LengthModifier::AsChar: return ArgType::AnyCharTy;
    286       case LengthModifier::AsShort: return Ctx.ShortTy;
    287       case LengthModifier::AsLong: return Ctx.LongTy;
    288       case LengthModifier::AsLongLong:
    289       case LengthModifier::AsQuad:
    290         return Ctx.LongLongTy;
    291       case LengthModifier::AsInt64:
    292         return ArgType(Ctx.LongLongTy, "__int64");
    293       case LengthModifier::AsIntMax:
    294         return ArgType(Ctx.getIntMaxType(), "intmax_t");
    295       case LengthModifier::AsSizeT:
    296         // FIXME: How to get the corresponding signed version of size_t?
    297         return ArgType();
    298       case LengthModifier::AsInt3264:
    299         return Ctx.getTargetInfo().getTriple().isArch64Bit()
    300                    ? ArgType(Ctx.LongLongTy, "__int64")
    301                    : ArgType(Ctx.IntTy, "__int32");
    302       case LengthModifier::AsPtrDiff:
    303         return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
    304       case LengthModifier::AsAllocate:
    305       case LengthModifier::AsMAllocate:
    306         return ArgType::Invalid();
    307     }
    308 
    309   if (CS.isUIntArg())
    310     switch (LM.getKind()) {
    311       case LengthModifier::AsLongDouble:
    312         // GNU extension.
    313         return Ctx.UnsignedLongLongTy;
    314       case LengthModifier::None:
    315         return Ctx.UnsignedIntTy;
    316       case LengthModifier::AsInt32:
    317         return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
    318       case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
    319       case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
    320       case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
    321       case LengthModifier::AsLongLong:
    322       case LengthModifier::AsQuad:
    323         return Ctx.UnsignedLongLongTy;
    324       case LengthModifier::AsInt64:
    325         return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
    326       case LengthModifier::AsIntMax:
    327         return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
    328       case LengthModifier::AsSizeT:
    329         return ArgType(Ctx.getSizeType(), "size_t");
    330       case LengthModifier::AsInt3264:
    331         return Ctx.getTargetInfo().getTriple().isArch64Bit()
    332                    ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
    333                    : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
    334       case LengthModifier::AsPtrDiff:
    335         // FIXME: How to get the corresponding unsigned
    336         // version of ptrdiff_t?
    337         return ArgType();
    338       case LengthModifier::AsAllocate:
    339       case LengthModifier::AsMAllocate:
    340         return ArgType::Invalid();
    341     }
    342 
    343   if (CS.isDoubleArg()) {
    344     if (LM.getKind() == LengthModifier::AsLongDouble)
    345       return Ctx.LongDoubleTy;
    346     return Ctx.DoubleTy;
    347   }
    348 
    349   if (CS.getKind() == ConversionSpecifier::nArg) {
    350     switch (LM.getKind()) {
    351       case LengthModifier::None:
    352         return ArgType::PtrTo(Ctx.IntTy);
    353       case LengthModifier::AsChar:
    354         return ArgType::PtrTo(Ctx.SignedCharTy);
    355       case LengthModifier::AsShort:
    356         return ArgType::PtrTo(Ctx.ShortTy);
    357       case LengthModifier::AsLong:
    358         return ArgType::PtrTo(Ctx.LongTy);
    359       case LengthModifier::AsLongLong:
    360       case LengthModifier::AsQuad:
    361         return ArgType::PtrTo(Ctx.LongLongTy);
    362       case LengthModifier::AsIntMax:
    363         return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
    364       case LengthModifier::AsSizeT:
    365         return ArgType(); // FIXME: ssize_t
    366       case LengthModifier::AsPtrDiff:
    367         return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
    368       case LengthModifier::AsLongDouble:
    369         return ArgType(); // FIXME: Is this a known extension?
    370       case LengthModifier::AsAllocate:
    371       case LengthModifier::AsMAllocate:
    372       case LengthModifier::AsInt32:
    373       case LengthModifier::AsInt3264:
    374       case LengthModifier::AsInt64:
    375         return ArgType::Invalid();
    376     }
    377   }
    378 
    379   switch (CS.getKind()) {
    380     case ConversionSpecifier::sArg:
    381       if (LM.getKind() == LengthModifier::AsWideChar) {
    382         if (IsObjCLiteral)
    383           return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
    384                          "const unichar *");
    385         return ArgType(ArgType::WCStrTy, "wchar_t *");
    386       }
    387       return ArgType::CStrTy;
    388     case ConversionSpecifier::SArg:
    389       if (IsObjCLiteral)
    390         return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
    391                        "const unichar *");
    392       return ArgType(ArgType::WCStrTy, "wchar_t *");
    393     case ConversionSpecifier::CArg:
    394       if (IsObjCLiteral)
    395         return ArgType(Ctx.UnsignedShortTy, "unichar");
    396       return ArgType(Ctx.WideCharTy, "wchar_t");
    397     case ConversionSpecifier::pArg:
    398       return ArgType::CPointerTy;
    399     case ConversionSpecifier::ObjCObjArg:
    400       return ArgType::ObjCPointerTy;
    401     default:
    402       break;
    403   }
    404 
    405   // FIXME: Handle other cases.
    406   return ArgType();
    407 }
    408 
    409 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
    410                               ASTContext &Ctx, bool IsObjCLiteral) {
    411   // %n is different from other conversion specifiers; don't try to fix it.
    412   if (CS.getKind() == ConversionSpecifier::nArg)
    413     return false;
    414 
    415   // Handle Objective-C objects first. Note that while the '%@' specifier will
    416   // not warn for structure pointer or void pointer arguments (because that's
    417   // how CoreFoundation objects are implemented), we only show a fixit for '%@'
    418   // if we know it's an object (block, id, class, or __attribute__((NSObject))).
    419   if (QT->isObjCRetainableType()) {
    420     if (!IsObjCLiteral)
    421       return false;
    422 
    423     CS.setKind(ConversionSpecifier::ObjCObjArg);
    424 
    425     // Disable irrelevant flags
    426     HasThousandsGrouping = false;
    427     HasPlusPrefix = false;
    428     HasSpacePrefix = false;
    429     HasAlternativeForm = false;
    430     HasLeadingZeroes = false;
    431     Precision.setHowSpecified(OptionalAmount::NotSpecified);
    432     LM.setKind(LengthModifier::None);
    433 
    434     return true;
    435   }
    436 
    437   // Handle strings next (char *, wchar_t *)
    438   if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
    439     CS.setKind(ConversionSpecifier::sArg);
    440 
    441     // Disable irrelevant flags
    442     HasAlternativeForm = 0;
    443     HasLeadingZeroes = 0;
    444 
    445     // Set the long length modifier for wide characters
    446     if (QT->getPointeeType()->isWideCharType())
    447       LM.setKind(LengthModifier::AsWideChar);
    448     else
    449       LM.setKind(LengthModifier::None);
    450 
    451     return true;
    452   }
    453 
    454   // If it's an enum, get its underlying type.
    455   if (const EnumType *ETy = QT->getAs<EnumType>())
    456     QT = ETy->getDecl()->getIntegerType();
    457 
    458   // We can only work with builtin types.
    459   const BuiltinType *BT = QT->getAs<BuiltinType>();
    460   if (!BT)
    461     return false;
    462 
    463   // Set length modifier
    464   switch (BT->getKind()) {
    465   case BuiltinType::Bool:
    466   case BuiltinType::WChar_U:
    467   case BuiltinType::WChar_S:
    468   case BuiltinType::Char16:
    469   case BuiltinType::Char32:
    470   case BuiltinType::UInt128:
    471   case BuiltinType::Int128:
    472   case BuiltinType::Half:
    473     // Various types which are non-trivial to correct.
    474     return false;
    475 
    476 #define SIGNED_TYPE(Id, SingletonId)
    477 #define UNSIGNED_TYPE(Id, SingletonId)
    478 #define FLOATING_TYPE(Id, SingletonId)
    479 #define BUILTIN_TYPE(Id, SingletonId) \
    480   case BuiltinType::Id:
    481 #include "clang/AST/BuiltinTypes.def"
    482     // Misc other stuff which doesn't make sense here.
    483     return false;
    484 
    485   case BuiltinType::UInt:
    486   case BuiltinType::Int:
    487   case BuiltinType::Float:
    488   case BuiltinType::Double:
    489     LM.setKind(LengthModifier::None);
    490     break;
    491 
    492   case BuiltinType::Char_U:
    493   case BuiltinType::UChar:
    494   case BuiltinType::Char_S:
    495   case BuiltinType::SChar:
    496     LM.setKind(LengthModifier::AsChar);
    497     break;
    498 
    499   case BuiltinType::Short:
    500   case BuiltinType::UShort:
    501     LM.setKind(LengthModifier::AsShort);
    502     break;
    503 
    504   case BuiltinType::Long:
    505   case BuiltinType::ULong:
    506     LM.setKind(LengthModifier::AsLong);
    507     break;
    508 
    509   case BuiltinType::LongLong:
    510   case BuiltinType::ULongLong:
    511     LM.setKind(LengthModifier::AsLongLong);
    512     break;
    513 
    514   case BuiltinType::LongDouble:
    515     LM.setKind(LengthModifier::AsLongDouble);
    516     break;
    517   }
    518 
    519   // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
    520   if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
    521     namedTypeToLengthModifier(QT, LM);
    522 
    523   // If fixing the length modifier was enough, we might be done.
    524   if (hasValidLengthModifier(Ctx.getTargetInfo())) {
    525     // If we're going to offer a fix anyway, make sure the sign matches.
    526     switch (CS.getKind()) {
    527     case ConversionSpecifier::uArg:
    528     case ConversionSpecifier::UArg:
    529       if (QT->isSignedIntegerType())
    530         CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
    531       break;
    532     case ConversionSpecifier::dArg:
    533     case ConversionSpecifier::DArg:
    534     case ConversionSpecifier::iArg:
    535       if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
    536         CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
    537       break;
    538     default:
    539       // Other specifiers do not have signed/unsigned variants.
    540       break;
    541     }
    542 
    543     const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
    544     if (ATR.isValid() && ATR.matchesType(Ctx, QT))
    545       return true;
    546   }
    547 
    548   // Set conversion specifier and disable any flags which do not apply to it.
    549   // Let typedefs to char fall through to int, as %c is silly for uint8_t.
    550   if (!isa<TypedefType>(QT) && QT->isCharType()) {
    551     CS.setKind(ConversionSpecifier::cArg);
    552     LM.setKind(LengthModifier::None);
    553     Precision.setHowSpecified(OptionalAmount::NotSpecified);
    554     HasAlternativeForm = 0;
    555     HasLeadingZeroes = 0;
    556     HasPlusPrefix = 0;
    557   }
    558   // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
    559   else if (QT->isRealFloatingType()) {
    560     CS.setKind(ConversionSpecifier::fArg);
    561   }
    562   else if (QT->isSignedIntegerType()) {
    563     CS.setKind(ConversionSpecifier::dArg);
    564     HasAlternativeForm = 0;
    565   }
    566   else if (QT->isUnsignedIntegerType()) {
    567     CS.setKind(ConversionSpecifier::uArg);
    568     HasAlternativeForm = 0;
    569     HasPlusPrefix = 0;
    570   } else {
    571     llvm_unreachable("Unexpected type");
    572   }
    573 
    574   return true;
    575 }
    576 
    577 void PrintfSpecifier::toString(raw_ostream &os) const {
    578   // Whilst some features have no defined order, we are using the order
    579   // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
    580   os << "%";
    581 
    582   // Positional args
    583   if (usesPositionalArg()) {
    584     os << getPositionalArgIndex() << "$";
    585   }
    586 
    587   // Conversion flags
    588   if (IsLeftJustified)    os << "-";
    589   if (HasPlusPrefix)      os << "+";
    590   if (HasSpacePrefix)     os << " ";
    591   if (HasAlternativeForm) os << "#";
    592   if (HasLeadingZeroes)   os << "0";
    593 
    594   // Minimum field width
    595   FieldWidth.toString(os);
    596   // Precision
    597   Precision.toString(os);
    598   // Length modifier
    599   os << LM.toString();
    600   // Conversion specifier
    601   os << CS.toString();
    602 }
    603 
    604 bool PrintfSpecifier::hasValidPlusPrefix() const {
    605   if (!HasPlusPrefix)
    606     return true;
    607 
    608   // The plus prefix only makes sense for signed conversions
    609   switch (CS.getKind()) {
    610   case ConversionSpecifier::dArg:
    611   case ConversionSpecifier::DArg:
    612   case ConversionSpecifier::iArg:
    613   case ConversionSpecifier::fArg:
    614   case ConversionSpecifier::FArg:
    615   case ConversionSpecifier::eArg:
    616   case ConversionSpecifier::EArg:
    617   case ConversionSpecifier::gArg:
    618   case ConversionSpecifier::GArg:
    619   case ConversionSpecifier::aArg:
    620   case ConversionSpecifier::AArg:
    621     return true;
    622 
    623   default:
    624     return false;
    625   }
    626 }
    627 
    628 bool PrintfSpecifier::hasValidAlternativeForm() const {
    629   if (!HasAlternativeForm)
    630     return true;
    631 
    632   // Alternate form flag only valid with the oxXaAeEfFgG conversions
    633   switch (CS.getKind()) {
    634   case ConversionSpecifier::oArg:
    635   case ConversionSpecifier::OArg:
    636   case ConversionSpecifier::xArg:
    637   case ConversionSpecifier::XArg:
    638   case ConversionSpecifier::aArg:
    639   case ConversionSpecifier::AArg:
    640   case ConversionSpecifier::eArg:
    641   case ConversionSpecifier::EArg:
    642   case ConversionSpecifier::fArg:
    643   case ConversionSpecifier::FArg:
    644   case ConversionSpecifier::gArg:
    645   case ConversionSpecifier::GArg:
    646     return true;
    647 
    648   default:
    649     return false;
    650   }
    651 }
    652 
    653 bool PrintfSpecifier::hasValidLeadingZeros() const {
    654   if (!HasLeadingZeroes)
    655     return true;
    656 
    657   // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
    658   switch (CS.getKind()) {
    659   case ConversionSpecifier::dArg:
    660   case ConversionSpecifier::DArg:
    661   case ConversionSpecifier::iArg:
    662   case ConversionSpecifier::oArg:
    663   case ConversionSpecifier::OArg:
    664   case ConversionSpecifier::uArg:
    665   case ConversionSpecifier::UArg:
    666   case ConversionSpecifier::xArg:
    667   case ConversionSpecifier::XArg:
    668   case ConversionSpecifier::aArg:
    669   case ConversionSpecifier::AArg:
    670   case ConversionSpecifier::eArg:
    671   case ConversionSpecifier::EArg:
    672   case ConversionSpecifier::fArg:
    673   case ConversionSpecifier::FArg:
    674   case ConversionSpecifier::gArg:
    675   case ConversionSpecifier::GArg:
    676     return true;
    677 
    678   default:
    679     return false;
    680   }
    681 }
    682 
    683 bool PrintfSpecifier::hasValidSpacePrefix() const {
    684   if (!HasSpacePrefix)
    685     return true;
    686 
    687   // The space prefix only makes sense for signed conversions
    688   switch (CS.getKind()) {
    689   case ConversionSpecifier::dArg:
    690   case ConversionSpecifier::DArg:
    691   case ConversionSpecifier::iArg:
    692   case ConversionSpecifier::fArg:
    693   case ConversionSpecifier::FArg:
    694   case ConversionSpecifier::eArg:
    695   case ConversionSpecifier::EArg:
    696   case ConversionSpecifier::gArg:
    697   case ConversionSpecifier::GArg:
    698   case ConversionSpecifier::aArg:
    699   case ConversionSpecifier::AArg:
    700     return true;
    701 
    702   default:
    703     return false;
    704   }
    705 }
    706 
    707 bool PrintfSpecifier::hasValidLeftJustified() const {
    708   if (!IsLeftJustified)
    709     return true;
    710 
    711   // The left justified flag is valid for all conversions except n
    712   switch (CS.getKind()) {
    713   case ConversionSpecifier::nArg:
    714     return false;
    715 
    716   default:
    717     return true;
    718   }
    719 }
    720 
    721 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
    722   if (!HasThousandsGrouping)
    723     return true;
    724 
    725   switch (CS.getKind()) {
    726     case ConversionSpecifier::dArg:
    727     case ConversionSpecifier::DArg:
    728     case ConversionSpecifier::iArg:
    729     case ConversionSpecifier::uArg:
    730     case ConversionSpecifier::UArg:
    731     case ConversionSpecifier::fArg:
    732     case ConversionSpecifier::FArg:
    733     case ConversionSpecifier::gArg:
    734     case ConversionSpecifier::GArg:
    735       return true;
    736     default:
    737       return false;
    738   }
    739 }
    740 
    741 bool PrintfSpecifier::hasValidPrecision() const {
    742   if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
    743     return true;
    744 
    745   // Precision is only valid with the diouxXaAeEfFgGs conversions
    746   switch (CS.getKind()) {
    747   case ConversionSpecifier::dArg:
    748   case ConversionSpecifier::DArg:
    749   case ConversionSpecifier::iArg:
    750   case ConversionSpecifier::oArg:
    751   case ConversionSpecifier::OArg:
    752   case ConversionSpecifier::uArg:
    753   case ConversionSpecifier::UArg:
    754   case ConversionSpecifier::xArg:
    755   case ConversionSpecifier::XArg:
    756   case ConversionSpecifier::aArg:
    757   case ConversionSpecifier::AArg:
    758   case ConversionSpecifier::eArg:
    759   case ConversionSpecifier::EArg:
    760   case ConversionSpecifier::fArg:
    761   case ConversionSpecifier::FArg:
    762   case ConversionSpecifier::gArg:
    763   case ConversionSpecifier::GArg:
    764   case ConversionSpecifier::sArg:
    765     return true;
    766 
    767   default:
    768     return false;
    769   }
    770 }
    771 bool PrintfSpecifier::hasValidFieldWidth() const {
    772   if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
    773       return true;
    774 
    775   // The field width is valid for all conversions except n
    776   switch (CS.getKind()) {
    777   case ConversionSpecifier::nArg:
    778     return false;
    779 
    780   default:
    781     return true;
    782   }
    783 }
    784