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