xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/PrintfFormatString.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Handling of format string in printf and friends.  The structure of format
100b57cec5SDimitry Andric // strings for fprintf() are described in C99 7.19.6.1.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
14*5ffd83dbSDimitry Andric #include "FormatStringParsing.h"
150b57cec5SDimitry Andric #include "clang/AST/FormatString.h"
160b57cec5SDimitry Andric #include "clang/AST/OSLog.h"
170b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
18*5ffd83dbSDimitry Andric #include "llvm/Support/Regex.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using clang::analyze_format_string::ArgType;
210b57cec5SDimitry Andric using clang::analyze_format_string::FormatStringHandler;
220b57cec5SDimitry Andric using clang::analyze_format_string::LengthModifier;
230b57cec5SDimitry Andric using clang::analyze_format_string::OptionalAmount;
240b57cec5SDimitry Andric using clang::analyze_format_string::ConversionSpecifier;
250b57cec5SDimitry Andric using clang::analyze_printf::PrintfSpecifier;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric using namespace clang;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
300b57cec5SDimitry Andric         PrintfSpecifierResult;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
330b57cec5SDimitry Andric // Methods for parsing format strings.
340b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using analyze_format_string::ParseNonPositionAmount;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
390b57cec5SDimitry Andric                            const char *Start, const char *&Beg, const char *E,
400b57cec5SDimitry Andric                            unsigned *argIndex) {
410b57cec5SDimitry Andric   if (argIndex) {
420b57cec5SDimitry Andric     FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
430b57cec5SDimitry Andric   } else {
440b57cec5SDimitry Andric     const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
450b57cec5SDimitry Andric                                            analyze_format_string::PrecisionPos);
460b57cec5SDimitry Andric     if (Amt.isInvalid())
470b57cec5SDimitry Andric       return true;
480b57cec5SDimitry Andric     FS.setPrecision(Amt);
490b57cec5SDimitry Andric   }
500b57cec5SDimitry Andric   return false;
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric static bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS,
540b57cec5SDimitry Andric                            const char *FlagBeg, const char *E, bool Warn) {
550b57cec5SDimitry Andric    StringRef Flag(FlagBeg, E - FlagBeg);
560b57cec5SDimitry Andric    // Currently there is only one flag.
570b57cec5SDimitry Andric    if (Flag == "tt") {
580b57cec5SDimitry Andric      FS.setHasObjCTechnicalTerm(FlagBeg);
590b57cec5SDimitry Andric      return false;
600b57cec5SDimitry Andric    }
610b57cec5SDimitry Andric    // Handle either the case of no flag or an invalid flag.
620b57cec5SDimitry Andric    if (Warn) {
630b57cec5SDimitry Andric      if (Flag == "")
640b57cec5SDimitry Andric        H.HandleEmptyObjCModifierFlag(FlagBeg, E  - FlagBeg);
650b57cec5SDimitry Andric      else
660b57cec5SDimitry Andric        H.HandleInvalidObjCModifierFlag(FlagBeg, E  - FlagBeg);
670b57cec5SDimitry Andric    }
680b57cec5SDimitry Andric    return true;
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
720b57cec5SDimitry Andric                                                   const char *&Beg,
730b57cec5SDimitry Andric                                                   const char *E,
740b57cec5SDimitry Andric                                                   unsigned &argIndex,
750b57cec5SDimitry Andric                                                   const LangOptions &LO,
760b57cec5SDimitry Andric                                                   const TargetInfo &Target,
770b57cec5SDimitry Andric                                                   bool Warn,
780b57cec5SDimitry Andric                                                   bool isFreeBSDKPrintf) {
790b57cec5SDimitry Andric 
800b57cec5SDimitry Andric   using namespace clang::analyze_format_string;
810b57cec5SDimitry Andric   using namespace clang::analyze_printf;
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   const char *I = Beg;
840b57cec5SDimitry Andric   const char *Start = nullptr;
850b57cec5SDimitry Andric   UpdateOnReturn <const char*> UpdateBeg(Beg, I);
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   // Look for a '%' character that indicates the start of a format specifier.
880b57cec5SDimitry Andric   for ( ; I != E ; ++I) {
890b57cec5SDimitry Andric     char c = *I;
900b57cec5SDimitry Andric     if (c == '\0') {
910b57cec5SDimitry Andric       // Detect spurious null characters, which are likely errors.
920b57cec5SDimitry Andric       H.HandleNullChar(I);
930b57cec5SDimitry Andric       return true;
940b57cec5SDimitry Andric     }
950b57cec5SDimitry Andric     if (c == '%') {
960b57cec5SDimitry Andric       Start = I++;  // Record the start of the format specifier.
970b57cec5SDimitry Andric       break;
980b57cec5SDimitry Andric     }
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   // No format specifier found?
1020b57cec5SDimitry Andric   if (!Start)
1030b57cec5SDimitry Andric     return false;
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   if (I == E) {
1060b57cec5SDimitry Andric     // No more characters left?
1070b57cec5SDimitry Andric     if (Warn)
1080b57cec5SDimitry Andric       H.HandleIncompleteSpecifier(Start, E - Start);
1090b57cec5SDimitry Andric     return true;
1100b57cec5SDimitry Andric   }
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   PrintfSpecifier FS;
1130b57cec5SDimitry Andric   if (ParseArgPosition(H, FS, Start, I, E))
1140b57cec5SDimitry Andric     return true;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   if (I == E) {
1170b57cec5SDimitry Andric     // No more characters left?
1180b57cec5SDimitry Andric     if (Warn)
1190b57cec5SDimitry Andric       H.HandleIncompleteSpecifier(Start, E - Start);
1200b57cec5SDimitry Andric     return true;
1210b57cec5SDimitry Andric   }
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   if (*I == '{') {
1240b57cec5SDimitry Andric     ++I;
1250b57cec5SDimitry Andric     unsigned char PrivacyFlags = 0;
1260b57cec5SDimitry Andric     StringRef MatchedStr;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric     do {
1290b57cec5SDimitry Andric       StringRef Str(I, E - I);
1300b57cec5SDimitry Andric       std::string Match = "^[[:space:]]*"
1310b57cec5SDimitry Andric                           "(private|public|sensitive|mask\\.[^[:space:],}]*)"
1320b57cec5SDimitry Andric                           "[[:space:]]*(,|})";
1330b57cec5SDimitry Andric       llvm::Regex R(Match);
1340b57cec5SDimitry Andric       SmallVector<StringRef, 2> Matches;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric       if (R.match(Str, &Matches)) {
1370b57cec5SDimitry Andric         MatchedStr = Matches[1];
1380b57cec5SDimitry Andric         I += Matches[0].size();
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric         // Set the privacy flag if the privacy annotation in the
1410b57cec5SDimitry Andric         // comma-delimited segment is at least as strict as the privacy
1420b57cec5SDimitry Andric         // annotations in previous comma-delimited segments.
1430b57cec5SDimitry Andric         if (MatchedStr.startswith("mask")) {
1440b57cec5SDimitry Andric           StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1);
1450b57cec5SDimitry Andric           unsigned Size = MaskType.size();
1460b57cec5SDimitry Andric           if (Warn && (Size == 0 || Size > 8))
1470b57cec5SDimitry Andric             H.handleInvalidMaskType(MaskType);
1480b57cec5SDimitry Andric           FS.setMaskType(MaskType);
1490b57cec5SDimitry Andric         } else if (MatchedStr.equals("sensitive"))
1500b57cec5SDimitry Andric           PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsSensitive;
1510b57cec5SDimitry Andric         else if (PrivacyFlags !=
1520b57cec5SDimitry Andric                  clang::analyze_os_log::OSLogBufferItem::IsSensitive &&
1530b57cec5SDimitry Andric                  MatchedStr.equals("private"))
1540b57cec5SDimitry Andric           PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;
1550b57cec5SDimitry Andric         else if (PrivacyFlags == 0 && MatchedStr.equals("public"))
1560b57cec5SDimitry Andric           PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;
1570b57cec5SDimitry Andric       } else {
1580b57cec5SDimitry Andric         size_t CommaOrBracePos =
1590b57cec5SDimitry Andric             Str.find_if([](char c) { return c == ',' || c == '}'; });
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric         if (CommaOrBracePos == StringRef::npos) {
1620b57cec5SDimitry Andric           // Neither a comma nor the closing brace was found.
1630b57cec5SDimitry Andric           if (Warn)
1640b57cec5SDimitry Andric             H.HandleIncompleteSpecifier(Start, E - Start);
1650b57cec5SDimitry Andric           return true;
1660b57cec5SDimitry Andric         }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric         I += CommaOrBracePos + 1;
1690b57cec5SDimitry Andric       }
1700b57cec5SDimitry Andric       // Continue until the closing brace is found.
1710b57cec5SDimitry Andric     } while (*(I - 1) == ',');
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric     // Set the privacy flag.
1740b57cec5SDimitry Andric     switch (PrivacyFlags) {
1750b57cec5SDimitry Andric     case 0:
1760b57cec5SDimitry Andric       break;
1770b57cec5SDimitry Andric     case clang::analyze_os_log::OSLogBufferItem::IsPrivate:
1780b57cec5SDimitry Andric       FS.setIsPrivate(MatchedStr.data());
1790b57cec5SDimitry Andric       break;
1800b57cec5SDimitry Andric     case clang::analyze_os_log::OSLogBufferItem::IsPublic:
1810b57cec5SDimitry Andric       FS.setIsPublic(MatchedStr.data());
1820b57cec5SDimitry Andric       break;
1830b57cec5SDimitry Andric     case clang::analyze_os_log::OSLogBufferItem::IsSensitive:
1840b57cec5SDimitry Andric       FS.setIsSensitive(MatchedStr.data());
1850b57cec5SDimitry Andric       break;
1860b57cec5SDimitry Andric     default:
1870b57cec5SDimitry Andric       llvm_unreachable("Unexpected privacy flag value");
1880b57cec5SDimitry Andric     }
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   // Look for flags (if any).
1920b57cec5SDimitry Andric   bool hasMore = true;
1930b57cec5SDimitry Andric   for ( ; I != E; ++I) {
1940b57cec5SDimitry Andric     switch (*I) {
1950b57cec5SDimitry Andric       default: hasMore = false; break;
1960b57cec5SDimitry Andric       case '\'':
1970b57cec5SDimitry Andric         // FIXME: POSIX specific.  Always accept?
1980b57cec5SDimitry Andric         FS.setHasThousandsGrouping(I);
1990b57cec5SDimitry Andric         break;
2000b57cec5SDimitry Andric       case '-': FS.setIsLeftJustified(I); break;
2010b57cec5SDimitry Andric       case '+': FS.setHasPlusPrefix(I); break;
2020b57cec5SDimitry Andric       case ' ': FS.setHasSpacePrefix(I); break;
2030b57cec5SDimitry Andric       case '#': FS.setHasAlternativeForm(I); break;
2040b57cec5SDimitry Andric       case '0': FS.setHasLeadingZeros(I); break;
2050b57cec5SDimitry Andric     }
2060b57cec5SDimitry Andric     if (!hasMore)
2070b57cec5SDimitry Andric       break;
2080b57cec5SDimitry Andric   }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric   if (I == E) {
2110b57cec5SDimitry Andric     // No more characters left?
2120b57cec5SDimitry Andric     if (Warn)
2130b57cec5SDimitry Andric       H.HandleIncompleteSpecifier(Start, E - Start);
2140b57cec5SDimitry Andric     return true;
2150b57cec5SDimitry Andric   }
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric   // Look for the field width (if any).
2180b57cec5SDimitry Andric   if (ParseFieldWidth(H, FS, Start, I, E,
2190b57cec5SDimitry Andric                       FS.usesPositionalArg() ? nullptr : &argIndex))
2200b57cec5SDimitry Andric     return true;
2210b57cec5SDimitry Andric 
2220b57cec5SDimitry Andric   if (I == E) {
2230b57cec5SDimitry Andric     // No more characters left?
2240b57cec5SDimitry Andric     if (Warn)
2250b57cec5SDimitry Andric       H.HandleIncompleteSpecifier(Start, E - Start);
2260b57cec5SDimitry Andric     return true;
2270b57cec5SDimitry Andric   }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric   // Look for the precision (if any).
2300b57cec5SDimitry Andric   if (*I == '.') {
2310b57cec5SDimitry Andric     ++I;
2320b57cec5SDimitry Andric     if (I == E) {
2330b57cec5SDimitry Andric       if (Warn)
2340b57cec5SDimitry Andric         H.HandleIncompleteSpecifier(Start, E - Start);
2350b57cec5SDimitry Andric       return true;
2360b57cec5SDimitry Andric     }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric     if (ParsePrecision(H, FS, Start, I, E,
2390b57cec5SDimitry Andric                        FS.usesPositionalArg() ? nullptr : &argIndex))
2400b57cec5SDimitry Andric       return true;
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric     if (I == E) {
2430b57cec5SDimitry Andric       // No more characters left?
2440b57cec5SDimitry Andric       if (Warn)
2450b57cec5SDimitry Andric         H.HandleIncompleteSpecifier(Start, E - Start);
2460b57cec5SDimitry Andric       return true;
2470b57cec5SDimitry Andric     }
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   if (ParseVectorModifier(H, FS, I, E, LO))
2510b57cec5SDimitry Andric     return true;
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric   // Look for the length modifier.
2540b57cec5SDimitry Andric   if (ParseLengthModifier(FS, I, E, LO) && I == E) {
2550b57cec5SDimitry Andric     // No more characters left?
2560b57cec5SDimitry Andric     if (Warn)
2570b57cec5SDimitry Andric       H.HandleIncompleteSpecifier(Start, E - Start);
2580b57cec5SDimitry Andric     return true;
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   // Look for the Objective-C modifier flags, if any.
2620b57cec5SDimitry Andric   // We parse these here, even if they don't apply to
2630b57cec5SDimitry Andric   // the conversion specifier, and then emit an error
2640b57cec5SDimitry Andric   // later if the conversion specifier isn't '@'.  This
2650b57cec5SDimitry Andric   // enables better recovery, and we don't know if
2660b57cec5SDimitry Andric   // these flags are applicable until later.
2670b57cec5SDimitry Andric   const char *ObjCModifierFlagsStart = nullptr,
2680b57cec5SDimitry Andric              *ObjCModifierFlagsEnd = nullptr;
2690b57cec5SDimitry Andric   if (*I == '[') {
2700b57cec5SDimitry Andric     ObjCModifierFlagsStart = I;
2710b57cec5SDimitry Andric     ++I;
2720b57cec5SDimitry Andric     auto flagStart = I;
2730b57cec5SDimitry Andric     for (;; ++I) {
2740b57cec5SDimitry Andric       ObjCModifierFlagsEnd = I;
2750b57cec5SDimitry Andric       if (I == E) {
2760b57cec5SDimitry Andric         if (Warn)
2770b57cec5SDimitry Andric           H.HandleIncompleteSpecifier(Start, E - Start);
2780b57cec5SDimitry Andric         return true;
2790b57cec5SDimitry Andric       }
2800b57cec5SDimitry Andric       // Did we find the closing ']'?
2810b57cec5SDimitry Andric       if (*I == ']') {
2820b57cec5SDimitry Andric         if (ParseObjCFlags(H, FS, flagStart, I, Warn))
2830b57cec5SDimitry Andric           return true;
2840b57cec5SDimitry Andric         ++I;
2850b57cec5SDimitry Andric         break;
2860b57cec5SDimitry Andric       }
2870b57cec5SDimitry Andric       // There are no separators defined yet for multiple
2880b57cec5SDimitry Andric       // Objective-C modifier flags.  When those are
2890b57cec5SDimitry Andric       // defined, this is the place to check.
2900b57cec5SDimitry Andric     }
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   if (*I == '\0') {
2940b57cec5SDimitry Andric     // Detect spurious null characters, which are likely errors.
2950b57cec5SDimitry Andric     H.HandleNullChar(I);
2960b57cec5SDimitry Andric     return true;
2970b57cec5SDimitry Andric   }
2980b57cec5SDimitry Andric 
2990b57cec5SDimitry Andric   // Finally, look for the conversion specifier.
3000b57cec5SDimitry Andric   const char *conversionPosition = I++;
3010b57cec5SDimitry Andric   ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
3020b57cec5SDimitry Andric   switch (*conversionPosition) {
3030b57cec5SDimitry Andric     default:
3040b57cec5SDimitry Andric       break;
3050b57cec5SDimitry Andric     // C99: 7.19.6.1 (section 8).
3060b57cec5SDimitry Andric     case '%': k = ConversionSpecifier::PercentArg;   break;
3070b57cec5SDimitry Andric     case 'A': k = ConversionSpecifier::AArg; break;
3080b57cec5SDimitry Andric     case 'E': k = ConversionSpecifier::EArg; break;
3090b57cec5SDimitry Andric     case 'F': k = ConversionSpecifier::FArg; break;
3100b57cec5SDimitry Andric     case 'G': k = ConversionSpecifier::GArg; break;
3110b57cec5SDimitry Andric     case 'X': k = ConversionSpecifier::XArg; break;
3120b57cec5SDimitry Andric     case 'a': k = ConversionSpecifier::aArg; break;
3130b57cec5SDimitry Andric     case 'c': k = ConversionSpecifier::cArg; break;
3140b57cec5SDimitry Andric     case 'd': k = ConversionSpecifier::dArg; break;
3150b57cec5SDimitry Andric     case 'e': k = ConversionSpecifier::eArg; break;
3160b57cec5SDimitry Andric     case 'f': k = ConversionSpecifier::fArg; break;
3170b57cec5SDimitry Andric     case 'g': k = ConversionSpecifier::gArg; break;
3180b57cec5SDimitry Andric     case 'i': k = ConversionSpecifier::iArg; break;
3190b57cec5SDimitry Andric     case 'n':
320*5ffd83dbSDimitry Andric       // Not handled, but reserved in OpenCL.
321*5ffd83dbSDimitry Andric       if (!LO.OpenCL)
3220b57cec5SDimitry Andric         k = ConversionSpecifier::nArg;
3230b57cec5SDimitry Andric       break;
3240b57cec5SDimitry Andric     case 'o': k = ConversionSpecifier::oArg; break;
3250b57cec5SDimitry Andric     case 'p': k = ConversionSpecifier::pArg; break;
3260b57cec5SDimitry Andric     case 's': k = ConversionSpecifier::sArg; break;
3270b57cec5SDimitry Andric     case 'u': k = ConversionSpecifier::uArg; break;
3280b57cec5SDimitry Andric     case 'x': k = ConversionSpecifier::xArg; break;
3290b57cec5SDimitry Andric     // POSIX specific.
3300b57cec5SDimitry Andric     case 'C': k = ConversionSpecifier::CArg; break;
3310b57cec5SDimitry Andric     case 'S': k = ConversionSpecifier::SArg; break;
3320b57cec5SDimitry Andric     // Apple extension for os_log
3330b57cec5SDimitry Andric     case 'P':
3340b57cec5SDimitry Andric       k = ConversionSpecifier::PArg;
3350b57cec5SDimitry Andric       break;
3360b57cec5SDimitry Andric     // Objective-C.
3370b57cec5SDimitry Andric     case '@': k = ConversionSpecifier::ObjCObjArg; break;
3380b57cec5SDimitry Andric     // Glibc specific.
3390b57cec5SDimitry Andric     case 'm': k = ConversionSpecifier::PrintErrno; break;
3400b57cec5SDimitry Andric     // FreeBSD kernel specific.
3410b57cec5SDimitry Andric     case 'b':
3420b57cec5SDimitry Andric       if (isFreeBSDKPrintf)
3430b57cec5SDimitry Andric         k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
3440b57cec5SDimitry Andric       break;
3450b57cec5SDimitry Andric     case 'r':
3460b57cec5SDimitry Andric       if (isFreeBSDKPrintf)
3470b57cec5SDimitry Andric         k = ConversionSpecifier::FreeBSDrArg; // int
3480b57cec5SDimitry Andric       break;
3490b57cec5SDimitry Andric     case 'y':
3500b57cec5SDimitry Andric       if (isFreeBSDKPrintf)
3510b57cec5SDimitry Andric         k = ConversionSpecifier::FreeBSDyArg; // int
3520b57cec5SDimitry Andric       break;
3530b57cec5SDimitry Andric     // Apple-specific.
3540b57cec5SDimitry Andric     case 'D':
3550b57cec5SDimitry Andric       if (isFreeBSDKPrintf)
3560b57cec5SDimitry Andric         k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
3570b57cec5SDimitry Andric       else if (Target.getTriple().isOSDarwin())
3580b57cec5SDimitry Andric         k = ConversionSpecifier::DArg;
3590b57cec5SDimitry Andric       break;
3600b57cec5SDimitry Andric     case 'O':
3610b57cec5SDimitry Andric       if (Target.getTriple().isOSDarwin())
3620b57cec5SDimitry Andric         k = ConversionSpecifier::OArg;
3630b57cec5SDimitry Andric       break;
3640b57cec5SDimitry Andric     case 'U':
3650b57cec5SDimitry Andric       if (Target.getTriple().isOSDarwin())
3660b57cec5SDimitry Andric         k = ConversionSpecifier::UArg;
3670b57cec5SDimitry Andric       break;
3680b57cec5SDimitry Andric     // MS specific.
3690b57cec5SDimitry Andric     case 'Z':
3700b57cec5SDimitry Andric       if (Target.getTriple().isOSMSVCRT())
3710b57cec5SDimitry Andric         k = ConversionSpecifier::ZArg;
3720b57cec5SDimitry Andric       break;
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   // Check to see if we used the Objective-C modifier flags with
3760b57cec5SDimitry Andric   // a conversion specifier other than '@'.
3770b57cec5SDimitry Andric   if (k != ConversionSpecifier::ObjCObjArg &&
3780b57cec5SDimitry Andric       k != ConversionSpecifier::InvalidSpecifier &&
3790b57cec5SDimitry Andric       ObjCModifierFlagsStart) {
3800b57cec5SDimitry Andric     H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
3810b57cec5SDimitry Andric                                            ObjCModifierFlagsEnd + 1,
3820b57cec5SDimitry Andric                                            conversionPosition);
3830b57cec5SDimitry Andric     return true;
3840b57cec5SDimitry Andric   }
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   PrintfConversionSpecifier CS(conversionPosition, k);
3870b57cec5SDimitry Andric   FS.setConversionSpecifier(CS);
3880b57cec5SDimitry Andric   if (CS.consumesDataArgument() && !FS.usesPositionalArg())
3890b57cec5SDimitry Andric     FS.setArgIndex(argIndex++);
3900b57cec5SDimitry Andric   // FreeBSD kernel specific.
3910b57cec5SDimitry Andric   if (k == ConversionSpecifier::FreeBSDbArg ||
3920b57cec5SDimitry Andric       k == ConversionSpecifier::FreeBSDDArg)
3930b57cec5SDimitry Andric     argIndex++;
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric   if (k == ConversionSpecifier::InvalidSpecifier) {
3960b57cec5SDimitry Andric     unsigned Len = I - Start;
3970b57cec5SDimitry Andric     if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
3980b57cec5SDimitry Andric       CS.setEndScanList(Start + Len);
3990b57cec5SDimitry Andric       FS.setConversionSpecifier(CS);
4000b57cec5SDimitry Andric     }
4010b57cec5SDimitry Andric     // Assume the conversion takes one argument.
4020b57cec5SDimitry Andric     return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
4030b57cec5SDimitry Andric   }
4040b57cec5SDimitry Andric   return PrintfSpecifierResult(Start, FS);
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
4080b57cec5SDimitry Andric                                                      const char *I,
4090b57cec5SDimitry Andric                                                      const char *E,
4100b57cec5SDimitry Andric                                                      const LangOptions &LO,
4110b57cec5SDimitry Andric                                                      const TargetInfo &Target,
4120b57cec5SDimitry Andric                                                      bool isFreeBSDKPrintf) {
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   unsigned argIndex = 0;
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   // Keep looking for a format specifier until we have exhausted the string.
4170b57cec5SDimitry Andric   while (I != E) {
4180b57cec5SDimitry Andric     const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
4190b57cec5SDimitry Andric                                                             LO, Target, true,
4200b57cec5SDimitry Andric                                                             isFreeBSDKPrintf);
4210b57cec5SDimitry Andric     // Did a fail-stop error of any kind occur when parsing the specifier?
4220b57cec5SDimitry Andric     // If so, don't do any more processing.
4230b57cec5SDimitry Andric     if (FSR.shouldStop())
4240b57cec5SDimitry Andric       return true;
4250b57cec5SDimitry Andric     // Did we exhaust the string or encounter an error that
4260b57cec5SDimitry Andric     // we can recover from?
4270b57cec5SDimitry Andric     if (!FSR.hasValue())
4280b57cec5SDimitry Andric       continue;
4290b57cec5SDimitry Andric     // We have a format specifier.  Pass it to the callback.
4300b57cec5SDimitry Andric     if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
4310b57cec5SDimitry Andric                                  I - FSR.getStart()))
4320b57cec5SDimitry Andric       return true;
4330b57cec5SDimitry Andric   }
4340b57cec5SDimitry Andric   assert(I == E && "Format string not exhausted");
4350b57cec5SDimitry Andric   return false;
4360b57cec5SDimitry Andric }
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
4390b57cec5SDimitry Andric                                                             const char *E,
4400b57cec5SDimitry Andric                                                             const LangOptions &LO,
4410b57cec5SDimitry Andric                                                             const TargetInfo &Target) {
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   unsigned argIndex = 0;
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric   // Keep looking for a %s format specifier until we have exhausted the string.
4460b57cec5SDimitry Andric   FormatStringHandler H;
4470b57cec5SDimitry Andric   while (I != E) {
4480b57cec5SDimitry Andric     const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
4490b57cec5SDimitry Andric                                                             LO, Target, false,
4500b57cec5SDimitry Andric                                                             false);
4510b57cec5SDimitry Andric     // Did a fail-stop error of any kind occur when parsing the specifier?
4520b57cec5SDimitry Andric     // If so, don't do any more processing.
4530b57cec5SDimitry Andric     if (FSR.shouldStop())
4540b57cec5SDimitry Andric       return false;
4550b57cec5SDimitry Andric     // Did we exhaust the string or encounter an error that
4560b57cec5SDimitry Andric     // we can recover from?
4570b57cec5SDimitry Andric     if (!FSR.hasValue())
4580b57cec5SDimitry Andric       continue;
4590b57cec5SDimitry Andric     const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
4600b57cec5SDimitry Andric     // Return true if this a %s format specifier.
4610b57cec5SDimitry Andric     if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
4620b57cec5SDimitry Andric       return true;
4630b57cec5SDimitry Andric   }
4640b57cec5SDimitry Andric   return false;
4650b57cec5SDimitry Andric }
4660b57cec5SDimitry Andric 
467a7dea167SDimitry Andric bool clang::analyze_format_string::parseFormatStringHasFormattingSpecifiers(
468a7dea167SDimitry Andric     const char *Begin, const char *End, const LangOptions &LO,
469a7dea167SDimitry Andric     const TargetInfo &Target) {
470a7dea167SDimitry Andric   unsigned ArgIndex = 0;
471a7dea167SDimitry Andric   // Keep looking for a formatting specifier until we have exhausted the string.
472a7dea167SDimitry Andric   FormatStringHandler H;
473a7dea167SDimitry Andric   while (Begin != End) {
474a7dea167SDimitry Andric     const PrintfSpecifierResult &FSR =
475a7dea167SDimitry Andric         ParsePrintfSpecifier(H, Begin, End, ArgIndex, LO, Target, false, false);
476a7dea167SDimitry Andric     if (FSR.shouldStop())
477a7dea167SDimitry Andric       break;
478a7dea167SDimitry Andric     if (FSR.hasValue())
479a7dea167SDimitry Andric       return true;
480a7dea167SDimitry Andric   }
481a7dea167SDimitry Andric   return false;
482a7dea167SDimitry Andric }
483a7dea167SDimitry Andric 
4840b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4850b57cec5SDimitry Andric // Methods on PrintfSpecifier.
4860b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4870b57cec5SDimitry Andric 
4880b57cec5SDimitry Andric ArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
4890b57cec5SDimitry Andric                                           bool IsObjCLiteral) const {
4900b57cec5SDimitry Andric   if (CS.getKind() == ConversionSpecifier::cArg)
4910b57cec5SDimitry Andric     switch (LM.getKind()) {
4920b57cec5SDimitry Andric       case LengthModifier::None:
4930b57cec5SDimitry Andric         return Ctx.IntTy;
4940b57cec5SDimitry Andric       case LengthModifier::AsLong:
4950b57cec5SDimitry Andric       case LengthModifier::AsWide:
4960b57cec5SDimitry Andric         return ArgType(ArgType::WIntTy, "wint_t");
4970b57cec5SDimitry Andric       case LengthModifier::AsShort:
4980b57cec5SDimitry Andric         if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
4990b57cec5SDimitry Andric           return Ctx.IntTy;
5000b57cec5SDimitry Andric         LLVM_FALLTHROUGH;
5010b57cec5SDimitry Andric       default:
5020b57cec5SDimitry Andric         return ArgType::Invalid();
5030b57cec5SDimitry Andric     }
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   if (CS.isIntArg())
5060b57cec5SDimitry Andric     switch (LM.getKind()) {
5070b57cec5SDimitry Andric       case LengthModifier::AsLongDouble:
5080b57cec5SDimitry Andric         // GNU extension.
5090b57cec5SDimitry Andric         return Ctx.LongLongTy;
5100b57cec5SDimitry Andric       case LengthModifier::None:
5110b57cec5SDimitry Andric       case LengthModifier::AsShortLong:
5120b57cec5SDimitry Andric         return Ctx.IntTy;
5130b57cec5SDimitry Andric       case LengthModifier::AsInt32:
5140b57cec5SDimitry Andric         return ArgType(Ctx.IntTy, "__int32");
5150b57cec5SDimitry Andric       case LengthModifier::AsChar:
5160b57cec5SDimitry Andric         return ArgType::AnyCharTy;
5170b57cec5SDimitry Andric       case LengthModifier::AsShort: return Ctx.ShortTy;
5180b57cec5SDimitry Andric       case LengthModifier::AsLong: return Ctx.LongTy;
5190b57cec5SDimitry Andric       case LengthModifier::AsLongLong:
5200b57cec5SDimitry Andric       case LengthModifier::AsQuad:
5210b57cec5SDimitry Andric         return Ctx.LongLongTy;
5220b57cec5SDimitry Andric       case LengthModifier::AsInt64:
5230b57cec5SDimitry Andric         return ArgType(Ctx.LongLongTy, "__int64");
5240b57cec5SDimitry Andric       case LengthModifier::AsIntMax:
5250b57cec5SDimitry Andric         return ArgType(Ctx.getIntMaxType(), "intmax_t");
5260b57cec5SDimitry Andric       case LengthModifier::AsSizeT:
5270b57cec5SDimitry Andric         return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
5280b57cec5SDimitry Andric       case LengthModifier::AsInt3264:
5290b57cec5SDimitry Andric         return Ctx.getTargetInfo().getTriple().isArch64Bit()
5300b57cec5SDimitry Andric                    ? ArgType(Ctx.LongLongTy, "__int64")
5310b57cec5SDimitry Andric                    : ArgType(Ctx.IntTy, "__int32");
5320b57cec5SDimitry Andric       case LengthModifier::AsPtrDiff:
5330b57cec5SDimitry Andric         return ArgType::makePtrdiffT(
5340b57cec5SDimitry Andric             ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
5350b57cec5SDimitry Andric       case LengthModifier::AsAllocate:
5360b57cec5SDimitry Andric       case LengthModifier::AsMAllocate:
5370b57cec5SDimitry Andric       case LengthModifier::AsWide:
5380b57cec5SDimitry Andric         return ArgType::Invalid();
5390b57cec5SDimitry Andric     }
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   if (CS.isUIntArg())
5420b57cec5SDimitry Andric     switch (LM.getKind()) {
5430b57cec5SDimitry Andric       case LengthModifier::AsLongDouble:
5440b57cec5SDimitry Andric         // GNU extension.
5450b57cec5SDimitry Andric         return Ctx.UnsignedLongLongTy;
5460b57cec5SDimitry Andric       case LengthModifier::None:
5470b57cec5SDimitry Andric       case LengthModifier::AsShortLong:
5480b57cec5SDimitry Andric         return Ctx.UnsignedIntTy;
5490b57cec5SDimitry Andric       case LengthModifier::AsInt32:
5500b57cec5SDimitry Andric         return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
5510b57cec5SDimitry Andric       case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
5520b57cec5SDimitry Andric       case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
5530b57cec5SDimitry Andric       case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
5540b57cec5SDimitry Andric       case LengthModifier::AsLongLong:
5550b57cec5SDimitry Andric       case LengthModifier::AsQuad:
5560b57cec5SDimitry Andric         return Ctx.UnsignedLongLongTy;
5570b57cec5SDimitry Andric       case LengthModifier::AsInt64:
5580b57cec5SDimitry Andric         return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
5590b57cec5SDimitry Andric       case LengthModifier::AsIntMax:
5600b57cec5SDimitry Andric         return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
5610b57cec5SDimitry Andric       case LengthModifier::AsSizeT:
5620b57cec5SDimitry Andric         return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
5630b57cec5SDimitry Andric       case LengthModifier::AsInt3264:
5640b57cec5SDimitry Andric         return Ctx.getTargetInfo().getTriple().isArch64Bit()
5650b57cec5SDimitry Andric                    ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
5660b57cec5SDimitry Andric                    : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
5670b57cec5SDimitry Andric       case LengthModifier::AsPtrDiff:
5680b57cec5SDimitry Andric         return ArgType::makePtrdiffT(
5690b57cec5SDimitry Andric             ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
5700b57cec5SDimitry Andric       case LengthModifier::AsAllocate:
5710b57cec5SDimitry Andric       case LengthModifier::AsMAllocate:
5720b57cec5SDimitry Andric       case LengthModifier::AsWide:
5730b57cec5SDimitry Andric         return ArgType::Invalid();
5740b57cec5SDimitry Andric     }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric   if (CS.isDoubleArg()) {
5770b57cec5SDimitry Andric     if (!VectorNumElts.isInvalid()) {
5780b57cec5SDimitry Andric       switch (LM.getKind()) {
5790b57cec5SDimitry Andric       case LengthModifier::AsShort:
5800b57cec5SDimitry Andric         return Ctx.HalfTy;
5810b57cec5SDimitry Andric       case LengthModifier::AsShortLong:
5820b57cec5SDimitry Andric         return Ctx.FloatTy;
5830b57cec5SDimitry Andric       case LengthModifier::AsLong:
5840b57cec5SDimitry Andric       default:
5850b57cec5SDimitry Andric         return Ctx.DoubleTy;
5860b57cec5SDimitry Andric       }
5870b57cec5SDimitry Andric     }
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric     if (LM.getKind() == LengthModifier::AsLongDouble)
5900b57cec5SDimitry Andric       return Ctx.LongDoubleTy;
5910b57cec5SDimitry Andric     return Ctx.DoubleTy;
5920b57cec5SDimitry Andric   }
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric   if (CS.getKind() == ConversionSpecifier::nArg) {
5950b57cec5SDimitry Andric     switch (LM.getKind()) {
5960b57cec5SDimitry Andric       case LengthModifier::None:
5970b57cec5SDimitry Andric         return ArgType::PtrTo(Ctx.IntTy);
5980b57cec5SDimitry Andric       case LengthModifier::AsChar:
5990b57cec5SDimitry Andric         return ArgType::PtrTo(Ctx.SignedCharTy);
6000b57cec5SDimitry Andric       case LengthModifier::AsShort:
6010b57cec5SDimitry Andric         return ArgType::PtrTo(Ctx.ShortTy);
6020b57cec5SDimitry Andric       case LengthModifier::AsLong:
6030b57cec5SDimitry Andric         return ArgType::PtrTo(Ctx.LongTy);
6040b57cec5SDimitry Andric       case LengthModifier::AsLongLong:
6050b57cec5SDimitry Andric       case LengthModifier::AsQuad:
6060b57cec5SDimitry Andric         return ArgType::PtrTo(Ctx.LongLongTy);
6070b57cec5SDimitry Andric       case LengthModifier::AsIntMax:
6080b57cec5SDimitry Andric         return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
6090b57cec5SDimitry Andric       case LengthModifier::AsSizeT:
6100b57cec5SDimitry Andric         return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
6110b57cec5SDimitry Andric       case LengthModifier::AsPtrDiff:
6120b57cec5SDimitry Andric         return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
6130b57cec5SDimitry Andric       case LengthModifier::AsLongDouble:
6140b57cec5SDimitry Andric         return ArgType(); // FIXME: Is this a known extension?
6150b57cec5SDimitry Andric       case LengthModifier::AsAllocate:
6160b57cec5SDimitry Andric       case LengthModifier::AsMAllocate:
6170b57cec5SDimitry Andric       case LengthModifier::AsInt32:
6180b57cec5SDimitry Andric       case LengthModifier::AsInt3264:
6190b57cec5SDimitry Andric       case LengthModifier::AsInt64:
6200b57cec5SDimitry Andric       case LengthModifier::AsWide:
6210b57cec5SDimitry Andric         return ArgType::Invalid();
6220b57cec5SDimitry Andric       case LengthModifier::AsShortLong:
6230b57cec5SDimitry Andric         llvm_unreachable("only used for OpenCL which doesn not handle nArg");
6240b57cec5SDimitry Andric     }
6250b57cec5SDimitry Andric   }
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric   switch (CS.getKind()) {
6280b57cec5SDimitry Andric     case ConversionSpecifier::sArg:
6290b57cec5SDimitry Andric       if (LM.getKind() == LengthModifier::AsWideChar) {
6300b57cec5SDimitry Andric         if (IsObjCLiteral)
6310b57cec5SDimitry Andric           return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
6320b57cec5SDimitry Andric                          "const unichar *");
6330b57cec5SDimitry Andric         return ArgType(ArgType::WCStrTy, "wchar_t *");
6340b57cec5SDimitry Andric       }
6350b57cec5SDimitry Andric       if (LM.getKind() == LengthModifier::AsWide)
6360b57cec5SDimitry Andric         return ArgType(ArgType::WCStrTy, "wchar_t *");
6370b57cec5SDimitry Andric       return ArgType::CStrTy;
6380b57cec5SDimitry Andric     case ConversionSpecifier::SArg:
6390b57cec5SDimitry Andric       if (IsObjCLiteral)
6400b57cec5SDimitry Andric         return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
6410b57cec5SDimitry Andric                        "const unichar *");
6420b57cec5SDimitry Andric       if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
6430b57cec5SDimitry Andric           LM.getKind() == LengthModifier::AsShort)
6440b57cec5SDimitry Andric         return ArgType::CStrTy;
6450b57cec5SDimitry Andric       return ArgType(ArgType::WCStrTy, "wchar_t *");
6460b57cec5SDimitry Andric     case ConversionSpecifier::CArg:
6470b57cec5SDimitry Andric       if (IsObjCLiteral)
6480b57cec5SDimitry Andric         return ArgType(Ctx.UnsignedShortTy, "unichar");
6490b57cec5SDimitry Andric       if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
6500b57cec5SDimitry Andric           LM.getKind() == LengthModifier::AsShort)
6510b57cec5SDimitry Andric         return Ctx.IntTy;
6520b57cec5SDimitry Andric       return ArgType(Ctx.WideCharTy, "wchar_t");
6530b57cec5SDimitry Andric     case ConversionSpecifier::pArg:
6540b57cec5SDimitry Andric     case ConversionSpecifier::PArg:
6550b57cec5SDimitry Andric       return ArgType::CPointerTy;
6560b57cec5SDimitry Andric     case ConversionSpecifier::ObjCObjArg:
6570b57cec5SDimitry Andric       return ArgType::ObjCPointerTy;
6580b57cec5SDimitry Andric     default:
6590b57cec5SDimitry Andric       break;
6600b57cec5SDimitry Andric   }
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric   // FIXME: Handle other cases.
6630b57cec5SDimitry Andric   return ArgType();
6640b57cec5SDimitry Andric }
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
6680b57cec5SDimitry Andric                                     bool IsObjCLiteral) const {
6690b57cec5SDimitry Andric   const PrintfConversionSpecifier &CS = getConversionSpecifier();
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric   if (!CS.consumesDataArgument())
6720b57cec5SDimitry Andric     return ArgType::Invalid();
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric   ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral);
6750b57cec5SDimitry Andric   if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
6760b57cec5SDimitry Andric     return ScalarTy;
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount());
6790b57cec5SDimitry Andric }
6800b57cec5SDimitry Andric 
6810b57cec5SDimitry Andric bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
6820b57cec5SDimitry Andric                               ASTContext &Ctx, bool IsObjCLiteral) {
6830b57cec5SDimitry Andric   // %n is different from other conversion specifiers; don't try to fix it.
6840b57cec5SDimitry Andric   if (CS.getKind() == ConversionSpecifier::nArg)
6850b57cec5SDimitry Andric     return false;
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric   // Handle Objective-C objects first. Note that while the '%@' specifier will
6880b57cec5SDimitry Andric   // not warn for structure pointer or void pointer arguments (because that's
6890b57cec5SDimitry Andric   // how CoreFoundation objects are implemented), we only show a fixit for '%@'
6900b57cec5SDimitry Andric   // if we know it's an object (block, id, class, or __attribute__((NSObject))).
6910b57cec5SDimitry Andric   if (QT->isObjCRetainableType()) {
6920b57cec5SDimitry Andric     if (!IsObjCLiteral)
6930b57cec5SDimitry Andric       return false;
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric     CS.setKind(ConversionSpecifier::ObjCObjArg);
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric     // Disable irrelevant flags
6980b57cec5SDimitry Andric     HasThousandsGrouping = false;
6990b57cec5SDimitry Andric     HasPlusPrefix = false;
7000b57cec5SDimitry Andric     HasSpacePrefix = false;
7010b57cec5SDimitry Andric     HasAlternativeForm = false;
7020b57cec5SDimitry Andric     HasLeadingZeroes = false;
7030b57cec5SDimitry Andric     Precision.setHowSpecified(OptionalAmount::NotSpecified);
7040b57cec5SDimitry Andric     LM.setKind(LengthModifier::None);
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric     return true;
7070b57cec5SDimitry Andric   }
7080b57cec5SDimitry Andric 
7090b57cec5SDimitry Andric   // Handle strings next (char *, wchar_t *)
7100b57cec5SDimitry Andric   if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
7110b57cec5SDimitry Andric     CS.setKind(ConversionSpecifier::sArg);
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric     // Disable irrelevant flags
7140b57cec5SDimitry Andric     HasAlternativeForm = 0;
7150b57cec5SDimitry Andric     HasLeadingZeroes = 0;
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric     // Set the long length modifier for wide characters
7180b57cec5SDimitry Andric     if (QT->getPointeeType()->isWideCharType())
7190b57cec5SDimitry Andric       LM.setKind(LengthModifier::AsWideChar);
7200b57cec5SDimitry Andric     else
7210b57cec5SDimitry Andric       LM.setKind(LengthModifier::None);
7220b57cec5SDimitry Andric 
7230b57cec5SDimitry Andric     return true;
7240b57cec5SDimitry Andric   }
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric   // If it's an enum, get its underlying type.
7270b57cec5SDimitry Andric   if (const EnumType *ETy = QT->getAs<EnumType>())
7280b57cec5SDimitry Andric     QT = ETy->getDecl()->getIntegerType();
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric   const BuiltinType *BT = QT->getAs<BuiltinType>();
7310b57cec5SDimitry Andric   if (!BT) {
7320b57cec5SDimitry Andric     const VectorType *VT = QT->getAs<VectorType>();
7330b57cec5SDimitry Andric     if (VT) {
7340b57cec5SDimitry Andric       QT = VT->getElementType();
7350b57cec5SDimitry Andric       BT = QT->getAs<BuiltinType>();
7360b57cec5SDimitry Andric       VectorNumElts = OptionalAmount(VT->getNumElements());
7370b57cec5SDimitry Andric     }
7380b57cec5SDimitry Andric   }
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric   // We can only work with builtin types.
7410b57cec5SDimitry Andric   if (!BT)
7420b57cec5SDimitry Andric     return false;
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric   // Set length modifier
7450b57cec5SDimitry Andric   switch (BT->getKind()) {
7460b57cec5SDimitry Andric   case BuiltinType::Bool:
7470b57cec5SDimitry Andric   case BuiltinType::WChar_U:
7480b57cec5SDimitry Andric   case BuiltinType::WChar_S:
7490b57cec5SDimitry Andric   case BuiltinType::Char8: // FIXME: Treat like 'char'?
7500b57cec5SDimitry Andric   case BuiltinType::Char16:
7510b57cec5SDimitry Andric   case BuiltinType::Char32:
7520b57cec5SDimitry Andric   case BuiltinType::UInt128:
7530b57cec5SDimitry Andric   case BuiltinType::Int128:
7540b57cec5SDimitry Andric   case BuiltinType::Half:
755*5ffd83dbSDimitry Andric   case BuiltinType::BFloat16:
7560b57cec5SDimitry Andric   case BuiltinType::Float16:
7570b57cec5SDimitry Andric   case BuiltinType::Float128:
7580b57cec5SDimitry Andric   case BuiltinType::ShortAccum:
7590b57cec5SDimitry Andric   case BuiltinType::Accum:
7600b57cec5SDimitry Andric   case BuiltinType::LongAccum:
7610b57cec5SDimitry Andric   case BuiltinType::UShortAccum:
7620b57cec5SDimitry Andric   case BuiltinType::UAccum:
7630b57cec5SDimitry Andric   case BuiltinType::ULongAccum:
7640b57cec5SDimitry Andric   case BuiltinType::ShortFract:
7650b57cec5SDimitry Andric   case BuiltinType::Fract:
7660b57cec5SDimitry Andric   case BuiltinType::LongFract:
7670b57cec5SDimitry Andric   case BuiltinType::UShortFract:
7680b57cec5SDimitry Andric   case BuiltinType::UFract:
7690b57cec5SDimitry Andric   case BuiltinType::ULongFract:
7700b57cec5SDimitry Andric   case BuiltinType::SatShortAccum:
7710b57cec5SDimitry Andric   case BuiltinType::SatAccum:
7720b57cec5SDimitry Andric   case BuiltinType::SatLongAccum:
7730b57cec5SDimitry Andric   case BuiltinType::SatUShortAccum:
7740b57cec5SDimitry Andric   case BuiltinType::SatUAccum:
7750b57cec5SDimitry Andric   case BuiltinType::SatULongAccum:
7760b57cec5SDimitry Andric   case BuiltinType::SatShortFract:
7770b57cec5SDimitry Andric   case BuiltinType::SatFract:
7780b57cec5SDimitry Andric   case BuiltinType::SatLongFract:
7790b57cec5SDimitry Andric   case BuiltinType::SatUShortFract:
7800b57cec5SDimitry Andric   case BuiltinType::SatUFract:
7810b57cec5SDimitry Andric   case BuiltinType::SatULongFract:
7820b57cec5SDimitry Andric     // Various types which are non-trivial to correct.
7830b57cec5SDimitry Andric     return false;
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
7860b57cec5SDimitry Andric   case BuiltinType::Id:
7870b57cec5SDimitry Andric #include "clang/Basic/OpenCLImageTypes.def"
7880b57cec5SDimitry Andric #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
7890b57cec5SDimitry Andric   case BuiltinType::Id:
7900b57cec5SDimitry Andric #include "clang/Basic/OpenCLExtensionTypes.def"
791a7dea167SDimitry Andric #define SVE_TYPE(Name, Id, SingletonId) \
792a7dea167SDimitry Andric   case BuiltinType::Id:
793a7dea167SDimitry Andric #include "clang/Basic/AArch64SVEACLETypes.def"
7940b57cec5SDimitry Andric #define SIGNED_TYPE(Id, SingletonId)
7950b57cec5SDimitry Andric #define UNSIGNED_TYPE(Id, SingletonId)
7960b57cec5SDimitry Andric #define FLOATING_TYPE(Id, SingletonId)
7970b57cec5SDimitry Andric #define BUILTIN_TYPE(Id, SingletonId) \
7980b57cec5SDimitry Andric   case BuiltinType::Id:
7990b57cec5SDimitry Andric #include "clang/AST/BuiltinTypes.def"
8000b57cec5SDimitry Andric     // Misc other stuff which doesn't make sense here.
8010b57cec5SDimitry Andric     return false;
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric   case BuiltinType::UInt:
8040b57cec5SDimitry Andric   case BuiltinType::Int:
8050b57cec5SDimitry Andric   case BuiltinType::Float:
8060b57cec5SDimitry Andric     LM.setKind(VectorNumElts.isInvalid() ?
8070b57cec5SDimitry Andric                LengthModifier::None : LengthModifier::AsShortLong);
8080b57cec5SDimitry Andric     break;
8090b57cec5SDimitry Andric   case BuiltinType::Double:
8100b57cec5SDimitry Andric     LM.setKind(VectorNumElts.isInvalid() ?
8110b57cec5SDimitry Andric                LengthModifier::None : LengthModifier::AsLong);
8120b57cec5SDimitry Andric     break;
8130b57cec5SDimitry Andric   case BuiltinType::Char_U:
8140b57cec5SDimitry Andric   case BuiltinType::UChar:
8150b57cec5SDimitry Andric   case BuiltinType::Char_S:
8160b57cec5SDimitry Andric   case BuiltinType::SChar:
8170b57cec5SDimitry Andric     LM.setKind(LengthModifier::AsChar);
8180b57cec5SDimitry Andric     break;
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric   case BuiltinType::Short:
8210b57cec5SDimitry Andric   case BuiltinType::UShort:
8220b57cec5SDimitry Andric     LM.setKind(LengthModifier::AsShort);
8230b57cec5SDimitry Andric     break;
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric   case BuiltinType::Long:
8260b57cec5SDimitry Andric   case BuiltinType::ULong:
8270b57cec5SDimitry Andric     LM.setKind(LengthModifier::AsLong);
8280b57cec5SDimitry Andric     break;
8290b57cec5SDimitry Andric 
8300b57cec5SDimitry Andric   case BuiltinType::LongLong:
8310b57cec5SDimitry Andric   case BuiltinType::ULongLong:
8320b57cec5SDimitry Andric     LM.setKind(LengthModifier::AsLongLong);
8330b57cec5SDimitry Andric     break;
8340b57cec5SDimitry Andric 
8350b57cec5SDimitry Andric   case BuiltinType::LongDouble:
8360b57cec5SDimitry Andric     LM.setKind(LengthModifier::AsLongDouble);
8370b57cec5SDimitry Andric     break;
8380b57cec5SDimitry Andric   }
8390b57cec5SDimitry Andric 
8400b57cec5SDimitry Andric   // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
8410b57cec5SDimitry Andric   if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
8420b57cec5SDimitry Andric     namedTypeToLengthModifier(QT, LM);
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric   // If fixing the length modifier was enough, we might be done.
8450b57cec5SDimitry Andric   if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
8460b57cec5SDimitry Andric     // If we're going to offer a fix anyway, make sure the sign matches.
8470b57cec5SDimitry Andric     switch (CS.getKind()) {
8480b57cec5SDimitry Andric     case ConversionSpecifier::uArg:
8490b57cec5SDimitry Andric     case ConversionSpecifier::UArg:
8500b57cec5SDimitry Andric       if (QT->isSignedIntegerType())
8510b57cec5SDimitry Andric         CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
8520b57cec5SDimitry Andric       break;
8530b57cec5SDimitry Andric     case ConversionSpecifier::dArg:
8540b57cec5SDimitry Andric     case ConversionSpecifier::DArg:
8550b57cec5SDimitry Andric     case ConversionSpecifier::iArg:
8560b57cec5SDimitry Andric       if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
8570b57cec5SDimitry Andric         CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
8580b57cec5SDimitry Andric       break;
8590b57cec5SDimitry Andric     default:
8600b57cec5SDimitry Andric       // Other specifiers do not have signed/unsigned variants.
8610b57cec5SDimitry Andric       break;
8620b57cec5SDimitry Andric     }
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric     const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
8650b57cec5SDimitry Andric     if (ATR.isValid() && ATR.matchesType(Ctx, QT))
8660b57cec5SDimitry Andric       return true;
8670b57cec5SDimitry Andric   }
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric   // Set conversion specifier and disable any flags which do not apply to it.
8700b57cec5SDimitry Andric   // Let typedefs to char fall through to int, as %c is silly for uint8_t.
8710b57cec5SDimitry Andric   if (!isa<TypedefType>(QT) && QT->isCharType()) {
8720b57cec5SDimitry Andric     CS.setKind(ConversionSpecifier::cArg);
8730b57cec5SDimitry Andric     LM.setKind(LengthModifier::None);
8740b57cec5SDimitry Andric     Precision.setHowSpecified(OptionalAmount::NotSpecified);
8750b57cec5SDimitry Andric     HasAlternativeForm = 0;
8760b57cec5SDimitry Andric     HasLeadingZeroes = 0;
8770b57cec5SDimitry Andric     HasPlusPrefix = 0;
8780b57cec5SDimitry Andric   }
8790b57cec5SDimitry Andric   // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
8800b57cec5SDimitry Andric   else if (QT->isRealFloatingType()) {
8810b57cec5SDimitry Andric     CS.setKind(ConversionSpecifier::fArg);
8820b57cec5SDimitry Andric   }
8830b57cec5SDimitry Andric   else if (QT->isSignedIntegerType()) {
8840b57cec5SDimitry Andric     CS.setKind(ConversionSpecifier::dArg);
8850b57cec5SDimitry Andric     HasAlternativeForm = 0;
8860b57cec5SDimitry Andric   }
8870b57cec5SDimitry Andric   else if (QT->isUnsignedIntegerType()) {
8880b57cec5SDimitry Andric     CS.setKind(ConversionSpecifier::uArg);
8890b57cec5SDimitry Andric     HasAlternativeForm = 0;
8900b57cec5SDimitry Andric     HasPlusPrefix = 0;
8910b57cec5SDimitry Andric   } else {
8920b57cec5SDimitry Andric     llvm_unreachable("Unexpected type");
8930b57cec5SDimitry Andric   }
8940b57cec5SDimitry Andric 
8950b57cec5SDimitry Andric   return true;
8960b57cec5SDimitry Andric }
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric void PrintfSpecifier::toString(raw_ostream &os) const {
8990b57cec5SDimitry Andric   // Whilst some features have no defined order, we are using the order
9000b57cec5SDimitry Andric   // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
9010b57cec5SDimitry Andric   os << "%";
9020b57cec5SDimitry Andric 
9030b57cec5SDimitry Andric   // Positional args
9040b57cec5SDimitry Andric   if (usesPositionalArg()) {
9050b57cec5SDimitry Andric     os << getPositionalArgIndex() << "$";
9060b57cec5SDimitry Andric   }
9070b57cec5SDimitry Andric 
9080b57cec5SDimitry Andric   // Conversion flags
9090b57cec5SDimitry Andric   if (IsLeftJustified)    os << "-";
9100b57cec5SDimitry Andric   if (HasPlusPrefix)      os << "+";
9110b57cec5SDimitry Andric   if (HasSpacePrefix)     os << " ";
9120b57cec5SDimitry Andric   if (HasAlternativeForm) os << "#";
9130b57cec5SDimitry Andric   if (HasLeadingZeroes)   os << "0";
9140b57cec5SDimitry Andric 
9150b57cec5SDimitry Andric   // Minimum field width
9160b57cec5SDimitry Andric   FieldWidth.toString(os);
9170b57cec5SDimitry Andric   // Precision
9180b57cec5SDimitry Andric   Precision.toString(os);
9190b57cec5SDimitry Andric 
9200b57cec5SDimitry Andric   // Vector modifier
9210b57cec5SDimitry Andric   if (!VectorNumElts.isInvalid())
9220b57cec5SDimitry Andric     os << 'v' << VectorNumElts.getConstantAmount();
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric   // Length modifier
9250b57cec5SDimitry Andric   os << LM.toString();
9260b57cec5SDimitry Andric   // Conversion specifier
9270b57cec5SDimitry Andric   os << CS.toString();
9280b57cec5SDimitry Andric }
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric bool PrintfSpecifier::hasValidPlusPrefix() const {
9310b57cec5SDimitry Andric   if (!HasPlusPrefix)
9320b57cec5SDimitry Andric     return true;
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric   // The plus prefix only makes sense for signed conversions
9350b57cec5SDimitry Andric   switch (CS.getKind()) {
9360b57cec5SDimitry Andric   case ConversionSpecifier::dArg:
9370b57cec5SDimitry Andric   case ConversionSpecifier::DArg:
9380b57cec5SDimitry Andric   case ConversionSpecifier::iArg:
9390b57cec5SDimitry Andric   case ConversionSpecifier::fArg:
9400b57cec5SDimitry Andric   case ConversionSpecifier::FArg:
9410b57cec5SDimitry Andric   case ConversionSpecifier::eArg:
9420b57cec5SDimitry Andric   case ConversionSpecifier::EArg:
9430b57cec5SDimitry Andric   case ConversionSpecifier::gArg:
9440b57cec5SDimitry Andric   case ConversionSpecifier::GArg:
9450b57cec5SDimitry Andric   case ConversionSpecifier::aArg:
9460b57cec5SDimitry Andric   case ConversionSpecifier::AArg:
9470b57cec5SDimitry Andric   case ConversionSpecifier::FreeBSDrArg:
9480b57cec5SDimitry Andric   case ConversionSpecifier::FreeBSDyArg:
9490b57cec5SDimitry Andric     return true;
9500b57cec5SDimitry Andric 
9510b57cec5SDimitry Andric   default:
9520b57cec5SDimitry Andric     return false;
9530b57cec5SDimitry Andric   }
9540b57cec5SDimitry Andric }
9550b57cec5SDimitry Andric 
9560b57cec5SDimitry Andric bool PrintfSpecifier::hasValidAlternativeForm() const {
9570b57cec5SDimitry Andric   if (!HasAlternativeForm)
9580b57cec5SDimitry Andric     return true;
9590b57cec5SDimitry Andric 
9600b57cec5SDimitry Andric   // Alternate form flag only valid with the oxXaAeEfFgG conversions
9610b57cec5SDimitry Andric   switch (CS.getKind()) {
9620b57cec5SDimitry Andric   case ConversionSpecifier::oArg:
9630b57cec5SDimitry Andric   case ConversionSpecifier::OArg:
9640b57cec5SDimitry Andric   case ConversionSpecifier::xArg:
9650b57cec5SDimitry Andric   case ConversionSpecifier::XArg:
9660b57cec5SDimitry Andric   case ConversionSpecifier::aArg:
9670b57cec5SDimitry Andric   case ConversionSpecifier::AArg:
9680b57cec5SDimitry Andric   case ConversionSpecifier::eArg:
9690b57cec5SDimitry Andric   case ConversionSpecifier::EArg:
9700b57cec5SDimitry Andric   case ConversionSpecifier::fArg:
9710b57cec5SDimitry Andric   case ConversionSpecifier::FArg:
9720b57cec5SDimitry Andric   case ConversionSpecifier::gArg:
9730b57cec5SDimitry Andric   case ConversionSpecifier::GArg:
9740b57cec5SDimitry Andric   case ConversionSpecifier::FreeBSDrArg:
9750b57cec5SDimitry Andric   case ConversionSpecifier::FreeBSDyArg:
9760b57cec5SDimitry Andric     return true;
9770b57cec5SDimitry Andric 
9780b57cec5SDimitry Andric   default:
9790b57cec5SDimitry Andric     return false;
9800b57cec5SDimitry Andric   }
9810b57cec5SDimitry Andric }
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric bool PrintfSpecifier::hasValidLeadingZeros() const {
9840b57cec5SDimitry Andric   if (!HasLeadingZeroes)
9850b57cec5SDimitry Andric     return true;
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric   // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
9880b57cec5SDimitry Andric   switch (CS.getKind()) {
9890b57cec5SDimitry Andric   case ConversionSpecifier::dArg:
9900b57cec5SDimitry Andric   case ConversionSpecifier::DArg:
9910b57cec5SDimitry Andric   case ConversionSpecifier::iArg:
9920b57cec5SDimitry Andric   case ConversionSpecifier::oArg:
9930b57cec5SDimitry Andric   case ConversionSpecifier::OArg:
9940b57cec5SDimitry Andric   case ConversionSpecifier::uArg:
9950b57cec5SDimitry Andric   case ConversionSpecifier::UArg:
9960b57cec5SDimitry Andric   case ConversionSpecifier::xArg:
9970b57cec5SDimitry Andric   case ConversionSpecifier::XArg:
9980b57cec5SDimitry Andric   case ConversionSpecifier::aArg:
9990b57cec5SDimitry Andric   case ConversionSpecifier::AArg:
10000b57cec5SDimitry Andric   case ConversionSpecifier::eArg:
10010b57cec5SDimitry Andric   case ConversionSpecifier::EArg:
10020b57cec5SDimitry Andric   case ConversionSpecifier::fArg:
10030b57cec5SDimitry Andric   case ConversionSpecifier::FArg:
10040b57cec5SDimitry Andric   case ConversionSpecifier::gArg:
10050b57cec5SDimitry Andric   case ConversionSpecifier::GArg:
10060b57cec5SDimitry Andric   case ConversionSpecifier::FreeBSDrArg:
10070b57cec5SDimitry Andric   case ConversionSpecifier::FreeBSDyArg:
10080b57cec5SDimitry Andric     return true;
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric   default:
10110b57cec5SDimitry Andric     return false;
10120b57cec5SDimitry Andric   }
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric bool PrintfSpecifier::hasValidSpacePrefix() const {
10160b57cec5SDimitry Andric   if (!HasSpacePrefix)
10170b57cec5SDimitry Andric     return true;
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   // The space prefix only makes sense for signed conversions
10200b57cec5SDimitry Andric   switch (CS.getKind()) {
10210b57cec5SDimitry Andric   case ConversionSpecifier::dArg:
10220b57cec5SDimitry Andric   case ConversionSpecifier::DArg:
10230b57cec5SDimitry Andric   case ConversionSpecifier::iArg:
10240b57cec5SDimitry Andric   case ConversionSpecifier::fArg:
10250b57cec5SDimitry Andric   case ConversionSpecifier::FArg:
10260b57cec5SDimitry Andric   case ConversionSpecifier::eArg:
10270b57cec5SDimitry Andric   case ConversionSpecifier::EArg:
10280b57cec5SDimitry Andric   case ConversionSpecifier::gArg:
10290b57cec5SDimitry Andric   case ConversionSpecifier::GArg:
10300b57cec5SDimitry Andric   case ConversionSpecifier::aArg:
10310b57cec5SDimitry Andric   case ConversionSpecifier::AArg:
10320b57cec5SDimitry Andric   case ConversionSpecifier::FreeBSDrArg:
10330b57cec5SDimitry Andric   case ConversionSpecifier::FreeBSDyArg:
10340b57cec5SDimitry Andric     return true;
10350b57cec5SDimitry Andric 
10360b57cec5SDimitry Andric   default:
10370b57cec5SDimitry Andric     return false;
10380b57cec5SDimitry Andric   }
10390b57cec5SDimitry Andric }
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric bool PrintfSpecifier::hasValidLeftJustified() const {
10420b57cec5SDimitry Andric   if (!IsLeftJustified)
10430b57cec5SDimitry Andric     return true;
10440b57cec5SDimitry Andric 
10450b57cec5SDimitry Andric   // The left justified flag is valid for all conversions except n
10460b57cec5SDimitry Andric   switch (CS.getKind()) {
10470b57cec5SDimitry Andric   case ConversionSpecifier::nArg:
10480b57cec5SDimitry Andric     return false;
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric   default:
10510b57cec5SDimitry Andric     return true;
10520b57cec5SDimitry Andric   }
10530b57cec5SDimitry Andric }
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
10560b57cec5SDimitry Andric   if (!HasThousandsGrouping)
10570b57cec5SDimitry Andric     return true;
10580b57cec5SDimitry Andric 
10590b57cec5SDimitry Andric   switch (CS.getKind()) {
10600b57cec5SDimitry Andric     case ConversionSpecifier::dArg:
10610b57cec5SDimitry Andric     case ConversionSpecifier::DArg:
10620b57cec5SDimitry Andric     case ConversionSpecifier::iArg:
10630b57cec5SDimitry Andric     case ConversionSpecifier::uArg:
10640b57cec5SDimitry Andric     case ConversionSpecifier::UArg:
10650b57cec5SDimitry Andric     case ConversionSpecifier::fArg:
10660b57cec5SDimitry Andric     case ConversionSpecifier::FArg:
10670b57cec5SDimitry Andric     case ConversionSpecifier::gArg:
10680b57cec5SDimitry Andric     case ConversionSpecifier::GArg:
10690b57cec5SDimitry Andric       return true;
10700b57cec5SDimitry Andric     default:
10710b57cec5SDimitry Andric       return false;
10720b57cec5SDimitry Andric   }
10730b57cec5SDimitry Andric }
10740b57cec5SDimitry Andric 
10750b57cec5SDimitry Andric bool PrintfSpecifier::hasValidPrecision() const {
10760b57cec5SDimitry Andric   if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
10770b57cec5SDimitry Andric     return true;
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric   // Precision is only valid with the diouxXaAeEfFgGsP conversions
10800b57cec5SDimitry Andric   switch (CS.getKind()) {
10810b57cec5SDimitry Andric   case ConversionSpecifier::dArg:
10820b57cec5SDimitry Andric   case ConversionSpecifier::DArg:
10830b57cec5SDimitry Andric   case ConversionSpecifier::iArg:
10840b57cec5SDimitry Andric   case ConversionSpecifier::oArg:
10850b57cec5SDimitry Andric   case ConversionSpecifier::OArg:
10860b57cec5SDimitry Andric   case ConversionSpecifier::uArg:
10870b57cec5SDimitry Andric   case ConversionSpecifier::UArg:
10880b57cec5SDimitry Andric   case ConversionSpecifier::xArg:
10890b57cec5SDimitry Andric   case ConversionSpecifier::XArg:
10900b57cec5SDimitry Andric   case ConversionSpecifier::aArg:
10910b57cec5SDimitry Andric   case ConversionSpecifier::AArg:
10920b57cec5SDimitry Andric   case ConversionSpecifier::eArg:
10930b57cec5SDimitry Andric   case ConversionSpecifier::EArg:
10940b57cec5SDimitry Andric   case ConversionSpecifier::fArg:
10950b57cec5SDimitry Andric   case ConversionSpecifier::FArg:
10960b57cec5SDimitry Andric   case ConversionSpecifier::gArg:
10970b57cec5SDimitry Andric   case ConversionSpecifier::GArg:
10980b57cec5SDimitry Andric   case ConversionSpecifier::sArg:
10990b57cec5SDimitry Andric   case ConversionSpecifier::FreeBSDrArg:
11000b57cec5SDimitry Andric   case ConversionSpecifier::FreeBSDyArg:
11010b57cec5SDimitry Andric   case ConversionSpecifier::PArg:
11020b57cec5SDimitry Andric     return true;
11030b57cec5SDimitry Andric 
11040b57cec5SDimitry Andric   default:
11050b57cec5SDimitry Andric     return false;
11060b57cec5SDimitry Andric   }
11070b57cec5SDimitry Andric }
11080b57cec5SDimitry Andric bool PrintfSpecifier::hasValidFieldWidth() const {
11090b57cec5SDimitry Andric   if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
11100b57cec5SDimitry Andric       return true;
11110b57cec5SDimitry Andric 
11120b57cec5SDimitry Andric   // The field width is valid for all conversions except n
11130b57cec5SDimitry Andric   switch (CS.getKind()) {
11140b57cec5SDimitry Andric   case ConversionSpecifier::nArg:
11150b57cec5SDimitry Andric     return false;
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric   default:
11180b57cec5SDimitry Andric     return true;
11190b57cec5SDimitry Andric   }
11200b57cec5SDimitry Andric }
1121