xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/FormatString.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
10b57cec5SDimitry Andric // FormatString.cpp - Common stuff for handling printf/scanf formats -*- 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 // Shared details for processing format strings of printf and scanf
100b57cec5SDimitry Andric // (and friends).
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "FormatStringParsing.h"
150b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
160b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
170b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.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::FormatSpecifier;
220b57cec5SDimitry Andric using clang::analyze_format_string::LengthModifier;
230b57cec5SDimitry Andric using clang::analyze_format_string::OptionalAmount;
240b57cec5SDimitry Andric using clang::analyze_format_string::PositionContext;
250b57cec5SDimitry Andric using clang::analyze_format_string::ConversionSpecifier;
260b57cec5SDimitry Andric using namespace clang;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric // Key function to FormatStringHandler.
290b57cec5SDimitry Andric FormatStringHandler::~FormatStringHandler() {}
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
320b57cec5SDimitry Andric // Functions for parsing format strings components in both printf and
330b57cec5SDimitry Andric // scanf format strings.
340b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric OptionalAmount
370b57cec5SDimitry Andric clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {
380b57cec5SDimitry Andric   const char *I = Beg;
390b57cec5SDimitry Andric   UpdateOnReturn <const char*> UpdateBeg(Beg, I);
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric   unsigned accumulator = 0;
420b57cec5SDimitry Andric   bool hasDigits = false;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   for ( ; I != E; ++I) {
450b57cec5SDimitry Andric     char c = *I;
460b57cec5SDimitry Andric     if (c >= '0' && c <= '9') {
470b57cec5SDimitry Andric       hasDigits = true;
480b57cec5SDimitry Andric       accumulator = (accumulator * 10) + (c - '0');
490b57cec5SDimitry Andric       continue;
500b57cec5SDimitry Andric     }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric     if (hasDigits)
530b57cec5SDimitry Andric       return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
540b57cec5SDimitry Andric           false);
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric     break;
570b57cec5SDimitry Andric   }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   return OptionalAmount();
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric OptionalAmount
630b57cec5SDimitry Andric clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,
640b57cec5SDimitry Andric                                                      const char *E,
650b57cec5SDimitry Andric                                                      unsigned &argIndex) {
660b57cec5SDimitry Andric   if (*Beg == '*') {
670b57cec5SDimitry Andric     ++Beg;
680b57cec5SDimitry Andric     return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
690b57cec5SDimitry Andric   }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   return ParseAmount(Beg, E);
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric OptionalAmount
750b57cec5SDimitry Andric clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,
760b57cec5SDimitry Andric                                                   const char *Start,
770b57cec5SDimitry Andric                                                   const char *&Beg,
780b57cec5SDimitry Andric                                                   const char *E,
790b57cec5SDimitry Andric                                                   PositionContext p) {
800b57cec5SDimitry Andric   if (*Beg == '*') {
810b57cec5SDimitry Andric     const char *I = Beg + 1;
820b57cec5SDimitry Andric     const OptionalAmount &Amt = ParseAmount(I, E);
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric     if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
850b57cec5SDimitry Andric       H.HandleInvalidPosition(Beg, I - Beg, p);
860b57cec5SDimitry Andric       return OptionalAmount(false);
870b57cec5SDimitry Andric     }
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric     if (I == E) {
900b57cec5SDimitry Andric       // No more characters left?
910b57cec5SDimitry Andric       H.HandleIncompleteSpecifier(Start, E - Start);
920b57cec5SDimitry Andric       return OptionalAmount(false);
930b57cec5SDimitry Andric     }
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric     assert(Amt.getHowSpecified() == OptionalAmount::Constant);
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric     if (*I == '$') {
980b57cec5SDimitry Andric       // Handle positional arguments
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric       // Special case: '*0$', since this is an easy mistake.
1010b57cec5SDimitry Andric       if (Amt.getConstantAmount() == 0) {
1020b57cec5SDimitry Andric         H.HandleZeroPosition(Beg, I - Beg + 1);
1030b57cec5SDimitry Andric         return OptionalAmount(false);
1040b57cec5SDimitry Andric       }
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric       const char *Tmp = Beg;
1070b57cec5SDimitry Andric       Beg = ++I;
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric       return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
1100b57cec5SDimitry Andric                             Tmp, 0, true);
1110b57cec5SDimitry Andric     }
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric     H.HandleInvalidPosition(Beg, I - Beg, p);
1140b57cec5SDimitry Andric     return OptionalAmount(false);
1150b57cec5SDimitry Andric   }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric   return ParseAmount(Beg, E);
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric bool
1220b57cec5SDimitry Andric clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,
1230b57cec5SDimitry Andric                                               FormatSpecifier &CS,
1240b57cec5SDimitry Andric                                               const char *Start,
1250b57cec5SDimitry Andric                                               const char *&Beg, const char *E,
1260b57cec5SDimitry Andric                                               unsigned *argIndex) {
1270b57cec5SDimitry Andric   // FIXME: Support negative field widths.
1280b57cec5SDimitry Andric   if (argIndex) {
1290b57cec5SDimitry Andric     CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
1300b57cec5SDimitry Andric   }
1310b57cec5SDimitry Andric   else {
1320b57cec5SDimitry Andric     const OptionalAmount Amt =
1330b57cec5SDimitry Andric       ParsePositionAmount(H, Start, Beg, E,
1340b57cec5SDimitry Andric                           analyze_format_string::FieldWidthPos);
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric     if (Amt.isInvalid())
1370b57cec5SDimitry Andric       return true;
1380b57cec5SDimitry Andric     CS.setFieldWidth(Amt);
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric   return false;
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric bool
1440b57cec5SDimitry Andric clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
1450b57cec5SDimitry Andric                                                FormatSpecifier &FS,
1460b57cec5SDimitry Andric                                                const char *Start,
1470b57cec5SDimitry Andric                                                const char *&Beg,
1480b57cec5SDimitry Andric                                                const char *E) {
1490b57cec5SDimitry Andric   const char *I = Beg;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   const OptionalAmount &Amt = ParseAmount(I, E);
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   if (I == E) {
1540b57cec5SDimitry Andric     // No more characters left?
1550b57cec5SDimitry Andric     H.HandleIncompleteSpecifier(Start, E - Start);
1560b57cec5SDimitry Andric     return true;
1570b57cec5SDimitry Andric   }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
1600b57cec5SDimitry Andric     // Warn that positional arguments are non-standard.
1610b57cec5SDimitry Andric     H.HandlePosition(Start, I - Start);
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric     // Special case: '%0$', since this is an easy mistake.
1640b57cec5SDimitry Andric     if (Amt.getConstantAmount() == 0) {
1650b57cec5SDimitry Andric       H.HandleZeroPosition(Start, I - Start);
1660b57cec5SDimitry Andric       return true;
1670b57cec5SDimitry Andric     }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric     FS.setArgIndex(Amt.getConstantAmount() - 1);
1700b57cec5SDimitry Andric     FS.setUsesPositionalArg();
1710b57cec5SDimitry Andric     // Update the caller's pointer if we decided to consume
1720b57cec5SDimitry Andric     // these characters.
1730b57cec5SDimitry Andric     Beg = I;
1740b57cec5SDimitry Andric     return false;
1750b57cec5SDimitry Andric   }
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   return false;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric bool
1810b57cec5SDimitry Andric clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H,
1820b57cec5SDimitry Andric                                                   FormatSpecifier &FS,
1830b57cec5SDimitry Andric                                                   const char *&I,
1840b57cec5SDimitry Andric                                                   const char *E,
1850b57cec5SDimitry Andric                                                   const LangOptions &LO) {
1860b57cec5SDimitry Andric   if (!LO.OpenCL)
1870b57cec5SDimitry Andric     return false;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   const char *Start = I;
1900b57cec5SDimitry Andric   if (*I == 'v') {
1910b57cec5SDimitry Andric     ++I;
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric     if (I == E) {
1940b57cec5SDimitry Andric       H.HandleIncompleteSpecifier(Start, E - Start);
1950b57cec5SDimitry Andric       return true;
1960b57cec5SDimitry Andric     }
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric     OptionalAmount NumElts = ParseAmount(I, E);
1990b57cec5SDimitry Andric     if (NumElts.getHowSpecified() != OptionalAmount::Constant) {
2000b57cec5SDimitry Andric       H.HandleIncompleteSpecifier(Start, E - Start);
2010b57cec5SDimitry Andric       return true;
2020b57cec5SDimitry Andric     }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric     FS.setVectorNumElts(NumElts);
2050b57cec5SDimitry Andric   }
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   return false;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric bool
2110b57cec5SDimitry Andric clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
2120b57cec5SDimitry Andric                                                   const char *&I,
2130b57cec5SDimitry Andric                                                   const char *E,
2140b57cec5SDimitry Andric                                                   const LangOptions &LO,
2150b57cec5SDimitry Andric                                                   bool IsScanf) {
2160b57cec5SDimitry Andric   LengthModifier::Kind lmKind = LengthModifier::None;
2170b57cec5SDimitry Andric   const char *lmPosition = I;
2180b57cec5SDimitry Andric   switch (*I) {
2190b57cec5SDimitry Andric     default:
2200b57cec5SDimitry Andric       return false;
2210b57cec5SDimitry Andric     case 'h':
2220b57cec5SDimitry Andric       ++I;
2230b57cec5SDimitry Andric       if (I != E && *I == 'h') {
2240b57cec5SDimitry Andric         ++I;
2250b57cec5SDimitry Andric         lmKind = LengthModifier::AsChar;
2260b57cec5SDimitry Andric       } else if (I != E && *I == 'l' && LO.OpenCL) {
2270b57cec5SDimitry Andric         ++I;
2280b57cec5SDimitry Andric         lmKind = LengthModifier::AsShortLong;
2290b57cec5SDimitry Andric       } else {
2300b57cec5SDimitry Andric         lmKind = LengthModifier::AsShort;
2310b57cec5SDimitry Andric       }
2320b57cec5SDimitry Andric       break;
2330b57cec5SDimitry Andric     case 'l':
2340b57cec5SDimitry Andric       ++I;
2350b57cec5SDimitry Andric       if (I != E && *I == 'l') {
2360b57cec5SDimitry Andric         ++I;
2370b57cec5SDimitry Andric         lmKind = LengthModifier::AsLongLong;
2380b57cec5SDimitry Andric       } else {
2390b57cec5SDimitry Andric         lmKind = LengthModifier::AsLong;
2400b57cec5SDimitry Andric       }
2410b57cec5SDimitry Andric       break;
2420b57cec5SDimitry Andric     case 'j': lmKind = LengthModifier::AsIntMax;     ++I; break;
2430b57cec5SDimitry Andric     case 'z': lmKind = LengthModifier::AsSizeT;      ++I; break;
2440b57cec5SDimitry Andric     case 't': lmKind = LengthModifier::AsPtrDiff;    ++I; break;
2450b57cec5SDimitry Andric     case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
2460b57cec5SDimitry Andric     case 'q': lmKind = LengthModifier::AsQuad;       ++I; break;
2470b57cec5SDimitry Andric     case 'a':
2480b57cec5SDimitry Andric       if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
2490b57cec5SDimitry Andric         // For scanf in C90, look at the next character to see if this should
2500b57cec5SDimitry Andric         // be parsed as the GNU extension 'a' length modifier. If not, this
2510b57cec5SDimitry Andric         // will be parsed as a conversion specifier.
2520b57cec5SDimitry Andric         ++I;
2530b57cec5SDimitry Andric         if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
2540b57cec5SDimitry Andric           lmKind = LengthModifier::AsAllocate;
2550b57cec5SDimitry Andric           break;
2560b57cec5SDimitry Andric         }
2570b57cec5SDimitry Andric         --I;
2580b57cec5SDimitry Andric       }
2590b57cec5SDimitry Andric       return false;
2600b57cec5SDimitry Andric     case 'm':
2610b57cec5SDimitry Andric       if (IsScanf) {
2620b57cec5SDimitry Andric         lmKind = LengthModifier::AsMAllocate;
2630b57cec5SDimitry Andric         ++I;
2640b57cec5SDimitry Andric         break;
2650b57cec5SDimitry Andric       }
2660b57cec5SDimitry Andric       return false;
2670b57cec5SDimitry Andric     // printf: AsInt64, AsInt32, AsInt3264
2680b57cec5SDimitry Andric     // scanf:  AsInt64
2690b57cec5SDimitry Andric     case 'I':
2700b57cec5SDimitry Andric       if (I + 1 != E && I + 2 != E) {
2710b57cec5SDimitry Andric         if (I[1] == '6' && I[2] == '4') {
2720b57cec5SDimitry Andric           I += 3;
2730b57cec5SDimitry Andric           lmKind = LengthModifier::AsInt64;
2740b57cec5SDimitry Andric           break;
2750b57cec5SDimitry Andric         }
2760b57cec5SDimitry Andric         if (IsScanf)
2770b57cec5SDimitry Andric           return false;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric         if (I[1] == '3' && I[2] == '2') {
2800b57cec5SDimitry Andric           I += 3;
2810b57cec5SDimitry Andric           lmKind = LengthModifier::AsInt32;
2820b57cec5SDimitry Andric           break;
2830b57cec5SDimitry Andric         }
2840b57cec5SDimitry Andric       }
2850b57cec5SDimitry Andric       ++I;
2860b57cec5SDimitry Andric       lmKind = LengthModifier::AsInt3264;
2870b57cec5SDimitry Andric       break;
2880b57cec5SDimitry Andric     case 'w':
2890b57cec5SDimitry Andric       lmKind = LengthModifier::AsWide; ++I; break;
2900b57cec5SDimitry Andric   }
2910b57cec5SDimitry Andric   LengthModifier lm(lmPosition, lmKind);
2920b57cec5SDimitry Andric   FS.setLengthModifier(lm);
2930b57cec5SDimitry Andric   return true;
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(
2970b57cec5SDimitry Andric     const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {
2980b57cec5SDimitry Andric   if (SpecifierBegin + 1 >= FmtStrEnd)
2990b57cec5SDimitry Andric     return false;
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   const llvm::UTF8 *SB =
3020b57cec5SDimitry Andric       reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);
3030b57cec5SDimitry Andric   const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);
3040b57cec5SDimitry Andric   const char FirstByte = *SB;
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   // If the invalid specifier is a multibyte UTF-8 string, return the
3070b57cec5SDimitry Andric   // total length accordingly so that the conversion specifier can be
3080b57cec5SDimitry Andric   // properly updated to reflect a complete UTF-8 specifier.
3090b57cec5SDimitry Andric   unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);
3100b57cec5SDimitry Andric   if (NumBytes == 1)
3110b57cec5SDimitry Andric     return false;
3120b57cec5SDimitry Andric   if (SB + NumBytes > SE)
3130b57cec5SDimitry Andric     return false;
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   Len = NumBytes + 1;
3160b57cec5SDimitry Andric   return true;
3170b57cec5SDimitry Andric }
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3200b57cec5SDimitry Andric // Methods on ArgType.
3210b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric clang::analyze_format_string::ArgType::MatchKind
3240b57cec5SDimitry Andric ArgType::matchesType(ASTContext &C, QualType argTy) const {
3250b57cec5SDimitry Andric   if (Ptr) {
3260b57cec5SDimitry Andric     // It has to be a pointer.
3270b57cec5SDimitry Andric     const PointerType *PT = argTy->getAs<PointerType>();
3280b57cec5SDimitry Andric     if (!PT)
3290b57cec5SDimitry Andric       return NoMatch;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric     // We cannot write through a const qualified pointer.
3320b57cec5SDimitry Andric     if (PT->getPointeeType().isConstQualified())
3330b57cec5SDimitry Andric       return NoMatch;
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric     argTy = PT->getPointeeType();
3360b57cec5SDimitry Andric   }
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   switch (K) {
3390b57cec5SDimitry Andric     case InvalidTy:
3400b57cec5SDimitry Andric       llvm_unreachable("ArgType must be valid");
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric     case UnknownTy:
3430b57cec5SDimitry Andric       return Match;
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric     case AnyCharTy: {
3460b57cec5SDimitry Andric       if (const EnumType *ETy = argTy->getAs<EnumType>()) {
3470b57cec5SDimitry Andric         // If the enum is incomplete we know nothing about the underlying type.
3480b57cec5SDimitry Andric         // Assume that it's 'int'.
3490b57cec5SDimitry Andric         if (!ETy->getDecl()->isComplete())
3500b57cec5SDimitry Andric           return NoMatch;
3510b57cec5SDimitry Andric         argTy = ETy->getDecl()->getIntegerType();
3520b57cec5SDimitry Andric       }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric       if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
3550b57cec5SDimitry Andric         switch (BT->getKind()) {
3560b57cec5SDimitry Andric           default:
3570b57cec5SDimitry Andric             break;
3580b57cec5SDimitry Andric           case BuiltinType::Char_S:
3590b57cec5SDimitry Andric           case BuiltinType::SChar:
3600b57cec5SDimitry Andric           case BuiltinType::UChar:
3610b57cec5SDimitry Andric           case BuiltinType::Char_U:
362a7dea167SDimitry Andric           case BuiltinType::Bool:
3630b57cec5SDimitry Andric             return Match;
3640b57cec5SDimitry Andric         }
3650b57cec5SDimitry Andric       return NoMatch;
3660b57cec5SDimitry Andric     }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric     case SpecificTy: {
3690b57cec5SDimitry Andric       if (const EnumType *ETy = argTy->getAs<EnumType>()) {
3700b57cec5SDimitry Andric         // If the enum is incomplete we know nothing about the underlying type.
3710b57cec5SDimitry Andric         // Assume that it's 'int'.
3720b57cec5SDimitry Andric         if (!ETy->getDecl()->isComplete())
3730b57cec5SDimitry Andric           argTy = C.IntTy;
3740b57cec5SDimitry Andric         else
3750b57cec5SDimitry Andric           argTy = ETy->getDecl()->getIntegerType();
3760b57cec5SDimitry Andric       }
3770b57cec5SDimitry Andric       argTy = C.getCanonicalType(argTy).getUnqualifiedType();
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric       if (T == argTy)
3800b57cec5SDimitry Andric         return Match;
3810b57cec5SDimitry Andric       // Check for "compatible types".
3820b57cec5SDimitry Andric       if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
3830b57cec5SDimitry Andric         switch (BT->getKind()) {
3840b57cec5SDimitry Andric           default:
3850b57cec5SDimitry Andric             break;
3860b57cec5SDimitry Andric           case BuiltinType::Char_S:
3870b57cec5SDimitry Andric           case BuiltinType::SChar:
3880b57cec5SDimitry Andric           case BuiltinType::Char_U:
3890b57cec5SDimitry Andric           case BuiltinType::UChar:
390a7dea167SDimitry Andric           case BuiltinType::Bool:
391a7dea167SDimitry Andric             if (T == C.UnsignedShortTy || T == C.ShortTy)
392a7dea167SDimitry Andric               return NoMatchTypeConfusion;
3930b57cec5SDimitry Andric             return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match
3940b57cec5SDimitry Andric                                                                 : NoMatch;
3950b57cec5SDimitry Andric           case BuiltinType::Short:
3960b57cec5SDimitry Andric             return T == C.UnsignedShortTy ? Match : NoMatch;
3970b57cec5SDimitry Andric           case BuiltinType::UShort:
3980b57cec5SDimitry Andric             return T == C.ShortTy ? Match : NoMatch;
3990b57cec5SDimitry Andric           case BuiltinType::Int:
4000b57cec5SDimitry Andric             return T == C.UnsignedIntTy ? Match : NoMatch;
4010b57cec5SDimitry Andric           case BuiltinType::UInt:
4020b57cec5SDimitry Andric             return T == C.IntTy ? Match : NoMatch;
4030b57cec5SDimitry Andric           case BuiltinType::Long:
4040b57cec5SDimitry Andric             return T == C.UnsignedLongTy ? Match : NoMatch;
4050b57cec5SDimitry Andric           case BuiltinType::ULong:
4060b57cec5SDimitry Andric             return T == C.LongTy ? Match : NoMatch;
4070b57cec5SDimitry Andric           case BuiltinType::LongLong:
4080b57cec5SDimitry Andric             return T == C.UnsignedLongLongTy ? Match : NoMatch;
4090b57cec5SDimitry Andric           case BuiltinType::ULongLong:
4100b57cec5SDimitry Andric             return T == C.LongLongTy ? Match : NoMatch;
4110b57cec5SDimitry Andric         }
4120b57cec5SDimitry Andric       return NoMatch;
4130b57cec5SDimitry Andric     }
4140b57cec5SDimitry Andric 
4150b57cec5SDimitry Andric     case CStrTy: {
4160b57cec5SDimitry Andric       const PointerType *PT = argTy->getAs<PointerType>();
4170b57cec5SDimitry Andric       if (!PT)
4180b57cec5SDimitry Andric         return NoMatch;
4190b57cec5SDimitry Andric       QualType pointeeTy = PT->getPointeeType();
4200b57cec5SDimitry Andric       if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
4210b57cec5SDimitry Andric         switch (BT->getKind()) {
4220b57cec5SDimitry Andric           case BuiltinType::Char_U:
4230b57cec5SDimitry Andric           case BuiltinType::UChar:
4240b57cec5SDimitry Andric           case BuiltinType::Char_S:
4250b57cec5SDimitry Andric           case BuiltinType::SChar:
4260b57cec5SDimitry Andric             return Match;
4270b57cec5SDimitry Andric           default:
4280b57cec5SDimitry Andric             break;
4290b57cec5SDimitry Andric         }
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric       return NoMatch;
4320b57cec5SDimitry Andric     }
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric     case WCStrTy: {
4350b57cec5SDimitry Andric       const PointerType *PT = argTy->getAs<PointerType>();
4360b57cec5SDimitry Andric       if (!PT)
4370b57cec5SDimitry Andric         return NoMatch;
4380b57cec5SDimitry Andric       QualType pointeeTy =
4390b57cec5SDimitry Andric         C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
4400b57cec5SDimitry Andric       return pointeeTy == C.getWideCharType() ? Match : NoMatch;
4410b57cec5SDimitry Andric     }
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric     case WIntTy: {
4440b57cec5SDimitry Andric       QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric       if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)
4470b57cec5SDimitry Andric         return Match;
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric       QualType PromoArg = argTy->isPromotableIntegerType()
4500b57cec5SDimitry Andric                               ? C.getPromotedIntegerType(argTy)
4510b57cec5SDimitry Andric                               : argTy;
4520b57cec5SDimitry Andric       PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric       // If the promoted argument is the corresponding signed type of the
4550b57cec5SDimitry Andric       // wint_t type, then it should match.
4560b57cec5SDimitry Andric       if (PromoArg->hasSignedIntegerRepresentation() &&
4570b57cec5SDimitry Andric           C.getCorrespondingUnsignedType(PromoArg) == WInt)
4580b57cec5SDimitry Andric         return Match;
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric       return WInt == PromoArg ? Match : NoMatch;
4610b57cec5SDimitry Andric     }
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric     case CPointerTy:
4640b57cec5SDimitry Andric       if (argTy->isVoidPointerType()) {
4650b57cec5SDimitry Andric         return Match;
4660b57cec5SDimitry Andric       } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
4670b57cec5SDimitry Andric             argTy->isBlockPointerType() || argTy->isNullPtrType()) {
4680b57cec5SDimitry Andric         return NoMatchPedantic;
4690b57cec5SDimitry Andric       } else {
4700b57cec5SDimitry Andric         return NoMatch;
4710b57cec5SDimitry Andric       }
4720b57cec5SDimitry Andric 
4730b57cec5SDimitry Andric     case ObjCPointerTy: {
4740b57cec5SDimitry Andric       if (argTy->getAs<ObjCObjectPointerType>() ||
4750b57cec5SDimitry Andric           argTy->getAs<BlockPointerType>())
4760b57cec5SDimitry Andric         return Match;
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric       // Handle implicit toll-free bridging.
4790b57cec5SDimitry Andric       if (const PointerType *PT = argTy->getAs<PointerType>()) {
4800b57cec5SDimitry Andric         // Things such as CFTypeRef are really just opaque pointers
4810b57cec5SDimitry Andric         // to C structs representing CF types that can often be bridged
4820b57cec5SDimitry Andric         // to Objective-C objects.  Since the compiler doesn't know which
4830b57cec5SDimitry Andric         // structs can be toll-free bridged, we just accept them all.
4840b57cec5SDimitry Andric         QualType pointee = PT->getPointeeType();
4850b57cec5SDimitry Andric         if (pointee->getAsStructureType() || pointee->isVoidType())
4860b57cec5SDimitry Andric           return Match;
4870b57cec5SDimitry Andric       }
4880b57cec5SDimitry Andric       return NoMatch;
4890b57cec5SDimitry Andric     }
4900b57cec5SDimitry Andric   }
4910b57cec5SDimitry Andric 
4920b57cec5SDimitry Andric   llvm_unreachable("Invalid ArgType Kind!");
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric 
4950b57cec5SDimitry Andric ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const {
4960b57cec5SDimitry Andric   // Check for valid vector element types.
4970b57cec5SDimitry Andric   if (T.isNull())
4980b57cec5SDimitry Andric     return ArgType::Invalid();
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric   QualType Vec = C.getExtVectorType(T, NumElts);
5010b57cec5SDimitry Andric   return ArgType(Vec, Name);
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric QualType ArgType::getRepresentativeType(ASTContext &C) const {
5050b57cec5SDimitry Andric   QualType Res;
5060b57cec5SDimitry Andric   switch (K) {
5070b57cec5SDimitry Andric     case InvalidTy:
5080b57cec5SDimitry Andric       llvm_unreachable("No representative type for Invalid ArgType");
5090b57cec5SDimitry Andric     case UnknownTy:
5100b57cec5SDimitry Andric       llvm_unreachable("No representative type for Unknown ArgType");
5110b57cec5SDimitry Andric     case AnyCharTy:
5120b57cec5SDimitry Andric       Res = C.CharTy;
5130b57cec5SDimitry Andric       break;
5140b57cec5SDimitry Andric     case SpecificTy:
5150b57cec5SDimitry Andric       Res = T;
5160b57cec5SDimitry Andric       break;
5170b57cec5SDimitry Andric     case CStrTy:
5180b57cec5SDimitry Andric       Res = C.getPointerType(C.CharTy);
5190b57cec5SDimitry Andric       break;
5200b57cec5SDimitry Andric     case WCStrTy:
5210b57cec5SDimitry Andric       Res = C.getPointerType(C.getWideCharType());
5220b57cec5SDimitry Andric       break;
5230b57cec5SDimitry Andric     case ObjCPointerTy:
5240b57cec5SDimitry Andric       Res = C.ObjCBuiltinIdTy;
5250b57cec5SDimitry Andric       break;
5260b57cec5SDimitry Andric     case CPointerTy:
5270b57cec5SDimitry Andric       Res = C.VoidPtrTy;
5280b57cec5SDimitry Andric       break;
5290b57cec5SDimitry Andric     case WIntTy: {
5300b57cec5SDimitry Andric       Res = C.getWIntType();
5310b57cec5SDimitry Andric       break;
5320b57cec5SDimitry Andric     }
5330b57cec5SDimitry Andric   }
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   if (Ptr)
5360b57cec5SDimitry Andric     Res = C.getPointerType(Res);
5370b57cec5SDimitry Andric   return Res;
5380b57cec5SDimitry Andric }
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {
541*5ffd83dbSDimitry Andric   std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy());
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   std::string Alias;
5440b57cec5SDimitry Andric   if (Name) {
5450b57cec5SDimitry Andric     // Use a specific name for this type, e.g. "size_t".
5460b57cec5SDimitry Andric     Alias = Name;
5470b57cec5SDimitry Andric     if (Ptr) {
5480b57cec5SDimitry Andric       // If ArgType is actually a pointer to T, append an asterisk.
5490b57cec5SDimitry Andric       Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";
5500b57cec5SDimitry Andric     }
5510b57cec5SDimitry Andric     // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
5520b57cec5SDimitry Andric     if (S == Alias)
5530b57cec5SDimitry Andric       Alias.clear();
5540b57cec5SDimitry Andric   }
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   if (!Alias.empty())
5570b57cec5SDimitry Andric     return std::string("'") + Alias + "' (aka '" + S + "')";
5580b57cec5SDimitry Andric   return std::string("'") + S + "'";
5590b57cec5SDimitry Andric }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5630b57cec5SDimitry Andric // Methods on OptionalAmount.
5640b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric ArgType
5670b57cec5SDimitry Andric analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {
5680b57cec5SDimitry Andric   return Ctx.IntTy;
5690b57cec5SDimitry Andric }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5720b57cec5SDimitry Andric // Methods on LengthModifier.
5730b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric const char *
5760b57cec5SDimitry Andric analyze_format_string::LengthModifier::toString() const {
5770b57cec5SDimitry Andric   switch (kind) {
5780b57cec5SDimitry Andric   case AsChar:
5790b57cec5SDimitry Andric     return "hh";
5800b57cec5SDimitry Andric   case AsShort:
5810b57cec5SDimitry Andric     return "h";
5820b57cec5SDimitry Andric   case AsShortLong:
5830b57cec5SDimitry Andric     return "hl";
5840b57cec5SDimitry Andric   case AsLong: // or AsWideChar
5850b57cec5SDimitry Andric     return "l";
5860b57cec5SDimitry Andric   case AsLongLong:
5870b57cec5SDimitry Andric     return "ll";
5880b57cec5SDimitry Andric   case AsQuad:
5890b57cec5SDimitry Andric     return "q";
5900b57cec5SDimitry Andric   case AsIntMax:
5910b57cec5SDimitry Andric     return "j";
5920b57cec5SDimitry Andric   case AsSizeT:
5930b57cec5SDimitry Andric     return "z";
5940b57cec5SDimitry Andric   case AsPtrDiff:
5950b57cec5SDimitry Andric     return "t";
5960b57cec5SDimitry Andric   case AsInt32:
5970b57cec5SDimitry Andric     return "I32";
5980b57cec5SDimitry Andric   case AsInt3264:
5990b57cec5SDimitry Andric     return "I";
6000b57cec5SDimitry Andric   case AsInt64:
6010b57cec5SDimitry Andric     return "I64";
6020b57cec5SDimitry Andric   case AsLongDouble:
6030b57cec5SDimitry Andric     return "L";
6040b57cec5SDimitry Andric   case AsAllocate:
6050b57cec5SDimitry Andric     return "a";
6060b57cec5SDimitry Andric   case AsMAllocate:
6070b57cec5SDimitry Andric     return "m";
6080b57cec5SDimitry Andric   case AsWide:
6090b57cec5SDimitry Andric     return "w";
6100b57cec5SDimitry Andric   case None:
6110b57cec5SDimitry Andric     return "";
6120b57cec5SDimitry Andric   }
6130b57cec5SDimitry Andric   return nullptr;
6140b57cec5SDimitry Andric }
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6170b57cec5SDimitry Andric // Methods on ConversionSpecifier.
6180b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric const char *ConversionSpecifier::toString() const {
6210b57cec5SDimitry Andric   switch (kind) {
6220b57cec5SDimitry Andric   case dArg: return "d";
6230b57cec5SDimitry Andric   case DArg: return "D";
6240b57cec5SDimitry Andric   case iArg: return "i";
6250b57cec5SDimitry Andric   case oArg: return "o";
6260b57cec5SDimitry Andric   case OArg: return "O";
6270b57cec5SDimitry Andric   case uArg: return "u";
6280b57cec5SDimitry Andric   case UArg: return "U";
6290b57cec5SDimitry Andric   case xArg: return "x";
6300b57cec5SDimitry Andric   case XArg: return "X";
6310b57cec5SDimitry Andric   case fArg: return "f";
6320b57cec5SDimitry Andric   case FArg: return "F";
6330b57cec5SDimitry Andric   case eArg: return "e";
6340b57cec5SDimitry Andric   case EArg: return "E";
6350b57cec5SDimitry Andric   case gArg: return "g";
6360b57cec5SDimitry Andric   case GArg: return "G";
6370b57cec5SDimitry Andric   case aArg: return "a";
6380b57cec5SDimitry Andric   case AArg: return "A";
6390b57cec5SDimitry Andric   case cArg: return "c";
6400b57cec5SDimitry Andric   case sArg: return "s";
6410b57cec5SDimitry Andric   case pArg: return "p";
6420b57cec5SDimitry Andric   case PArg:
6430b57cec5SDimitry Andric     return "P";
6440b57cec5SDimitry Andric   case nArg: return "n";
6450b57cec5SDimitry Andric   case PercentArg:  return "%";
6460b57cec5SDimitry Andric   case ScanListArg: return "[";
6470b57cec5SDimitry Andric   case InvalidSpecifier: return nullptr;
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric   // POSIX unicode extensions.
6500b57cec5SDimitry Andric   case CArg: return "C";
6510b57cec5SDimitry Andric   case SArg: return "S";
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric   // Objective-C specific specifiers.
6540b57cec5SDimitry Andric   case ObjCObjArg: return "@";
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric   // FreeBSD kernel specific specifiers.
6570b57cec5SDimitry Andric   case FreeBSDbArg: return "b";
6580b57cec5SDimitry Andric   case FreeBSDDArg: return "D";
6590b57cec5SDimitry Andric   case FreeBSDrArg: return "r";
6600b57cec5SDimitry Andric   case FreeBSDyArg: return "y";
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric   // GlibC specific specifiers.
6630b57cec5SDimitry Andric   case PrintErrno: return "m";
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   // MS specific specifiers.
6660b57cec5SDimitry Andric   case ZArg: return "Z";
6670b57cec5SDimitry Andric   }
6680b57cec5SDimitry Andric   return nullptr;
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric Optional<ConversionSpecifier>
6720b57cec5SDimitry Andric ConversionSpecifier::getStandardSpecifier() const {
6730b57cec5SDimitry Andric   ConversionSpecifier::Kind NewKind;
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric   switch (getKind()) {
6760b57cec5SDimitry Andric   default:
6770b57cec5SDimitry Andric     return None;
6780b57cec5SDimitry Andric   case DArg:
6790b57cec5SDimitry Andric     NewKind = dArg;
6800b57cec5SDimitry Andric     break;
6810b57cec5SDimitry Andric   case UArg:
6820b57cec5SDimitry Andric     NewKind = uArg;
6830b57cec5SDimitry Andric     break;
6840b57cec5SDimitry Andric   case OArg:
6850b57cec5SDimitry Andric     NewKind = oArg;
6860b57cec5SDimitry Andric     break;
6870b57cec5SDimitry Andric   }
6880b57cec5SDimitry Andric 
6890b57cec5SDimitry Andric   ConversionSpecifier FixedCS(*this);
6900b57cec5SDimitry Andric   FixedCS.setKind(NewKind);
6910b57cec5SDimitry Andric   return FixedCS;
6920b57cec5SDimitry Andric }
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6950b57cec5SDimitry Andric // Methods on OptionalAmount.
6960b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric void OptionalAmount::toString(raw_ostream &os) const {
6990b57cec5SDimitry Andric   switch (hs) {
7000b57cec5SDimitry Andric   case Invalid:
7010b57cec5SDimitry Andric   case NotSpecified:
7020b57cec5SDimitry Andric     return;
7030b57cec5SDimitry Andric   case Arg:
7040b57cec5SDimitry Andric     if (UsesDotPrefix)
7050b57cec5SDimitry Andric         os << ".";
7060b57cec5SDimitry Andric     if (usesPositionalArg())
7070b57cec5SDimitry Andric       os << "*" << getPositionalArgIndex() << "$";
7080b57cec5SDimitry Andric     else
7090b57cec5SDimitry Andric       os << "*";
7100b57cec5SDimitry Andric     break;
7110b57cec5SDimitry Andric   case Constant:
7120b57cec5SDimitry Andric     if (UsesDotPrefix)
7130b57cec5SDimitry Andric         os << ".";
7140b57cec5SDimitry Andric     os << amt;
7150b57cec5SDimitry Andric     break;
7160b57cec5SDimitry Andric   }
7170b57cec5SDimitry Andric }
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target,
7200b57cec5SDimitry Andric                                              const LangOptions &LO) const {
7210b57cec5SDimitry Andric   switch (LM.getKind()) {
7220b57cec5SDimitry Andric     case LengthModifier::None:
7230b57cec5SDimitry Andric       return true;
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric     // Handle most integer flags
7260b57cec5SDimitry Andric     case LengthModifier::AsShort:
7270b57cec5SDimitry Andric       // Length modifier only applies to FP vectors.
7280b57cec5SDimitry Andric       if (LO.OpenCL && CS.isDoubleArg())
7290b57cec5SDimitry Andric         return !VectorNumElts.isInvalid();
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric       if (Target.getTriple().isOSMSVCRT()) {
7320b57cec5SDimitry Andric         switch (CS.getKind()) {
7330b57cec5SDimitry Andric           case ConversionSpecifier::cArg:
7340b57cec5SDimitry Andric           case ConversionSpecifier::CArg:
7350b57cec5SDimitry Andric           case ConversionSpecifier::sArg:
7360b57cec5SDimitry Andric           case ConversionSpecifier::SArg:
7370b57cec5SDimitry Andric           case ConversionSpecifier::ZArg:
7380b57cec5SDimitry Andric             return true;
7390b57cec5SDimitry Andric           default:
7400b57cec5SDimitry Andric             break;
7410b57cec5SDimitry Andric         }
7420b57cec5SDimitry Andric       }
7430b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
7440b57cec5SDimitry Andric     case LengthModifier::AsChar:
7450b57cec5SDimitry Andric     case LengthModifier::AsLongLong:
7460b57cec5SDimitry Andric     case LengthModifier::AsQuad:
7470b57cec5SDimitry Andric     case LengthModifier::AsIntMax:
7480b57cec5SDimitry Andric     case LengthModifier::AsSizeT:
7490b57cec5SDimitry Andric     case LengthModifier::AsPtrDiff:
7500b57cec5SDimitry Andric       switch (CS.getKind()) {
7510b57cec5SDimitry Andric         case ConversionSpecifier::dArg:
7520b57cec5SDimitry Andric         case ConversionSpecifier::DArg:
7530b57cec5SDimitry Andric         case ConversionSpecifier::iArg:
7540b57cec5SDimitry Andric         case ConversionSpecifier::oArg:
7550b57cec5SDimitry Andric         case ConversionSpecifier::OArg:
7560b57cec5SDimitry Andric         case ConversionSpecifier::uArg:
7570b57cec5SDimitry Andric         case ConversionSpecifier::UArg:
7580b57cec5SDimitry Andric         case ConversionSpecifier::xArg:
7590b57cec5SDimitry Andric         case ConversionSpecifier::XArg:
7600b57cec5SDimitry Andric         case ConversionSpecifier::nArg:
7610b57cec5SDimitry Andric           return true;
7620b57cec5SDimitry Andric         case ConversionSpecifier::FreeBSDrArg:
7630b57cec5SDimitry Andric         case ConversionSpecifier::FreeBSDyArg:
7640b57cec5SDimitry Andric           return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();
7650b57cec5SDimitry Andric         default:
7660b57cec5SDimitry Andric           return false;
7670b57cec5SDimitry Andric       }
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric     case LengthModifier::AsShortLong:
7700b57cec5SDimitry Andric       return LO.OpenCL && !VectorNumElts.isInvalid();
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric     // Handle 'l' flag
7730b57cec5SDimitry Andric     case LengthModifier::AsLong: // or AsWideChar
7740b57cec5SDimitry Andric       if (CS.isDoubleArg()) {
7750b57cec5SDimitry Andric         // Invalid for OpenCL FP scalars.
7760b57cec5SDimitry Andric         if (LO.OpenCL && VectorNumElts.isInvalid())
7770b57cec5SDimitry Andric           return false;
7780b57cec5SDimitry Andric         return true;
7790b57cec5SDimitry Andric       }
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric       switch (CS.getKind()) {
7820b57cec5SDimitry Andric         case ConversionSpecifier::dArg:
7830b57cec5SDimitry Andric         case ConversionSpecifier::DArg:
7840b57cec5SDimitry Andric         case ConversionSpecifier::iArg:
7850b57cec5SDimitry Andric         case ConversionSpecifier::oArg:
7860b57cec5SDimitry Andric         case ConversionSpecifier::OArg:
7870b57cec5SDimitry Andric         case ConversionSpecifier::uArg:
7880b57cec5SDimitry Andric         case ConversionSpecifier::UArg:
7890b57cec5SDimitry Andric         case ConversionSpecifier::xArg:
7900b57cec5SDimitry Andric         case ConversionSpecifier::XArg:
7910b57cec5SDimitry Andric         case ConversionSpecifier::nArg:
7920b57cec5SDimitry Andric         case ConversionSpecifier::cArg:
7930b57cec5SDimitry Andric         case ConversionSpecifier::sArg:
7940b57cec5SDimitry Andric         case ConversionSpecifier::ScanListArg:
7950b57cec5SDimitry Andric         case ConversionSpecifier::ZArg:
7960b57cec5SDimitry Andric           return true;
7970b57cec5SDimitry Andric         case ConversionSpecifier::FreeBSDrArg:
7980b57cec5SDimitry Andric         case ConversionSpecifier::FreeBSDyArg:
7990b57cec5SDimitry Andric           return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();
8000b57cec5SDimitry Andric         default:
8010b57cec5SDimitry Andric           return false;
8020b57cec5SDimitry Andric       }
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric     case LengthModifier::AsLongDouble:
8050b57cec5SDimitry Andric       switch (CS.getKind()) {
8060b57cec5SDimitry Andric         case ConversionSpecifier::aArg:
8070b57cec5SDimitry Andric         case ConversionSpecifier::AArg:
8080b57cec5SDimitry Andric         case ConversionSpecifier::fArg:
8090b57cec5SDimitry Andric         case ConversionSpecifier::FArg:
8100b57cec5SDimitry Andric         case ConversionSpecifier::eArg:
8110b57cec5SDimitry Andric         case ConversionSpecifier::EArg:
8120b57cec5SDimitry Andric         case ConversionSpecifier::gArg:
8130b57cec5SDimitry Andric         case ConversionSpecifier::GArg:
8140b57cec5SDimitry Andric           return true;
8150b57cec5SDimitry Andric         // GNU libc extension.
8160b57cec5SDimitry Andric         case ConversionSpecifier::dArg:
8170b57cec5SDimitry Andric         case ConversionSpecifier::iArg:
8180b57cec5SDimitry Andric         case ConversionSpecifier::oArg:
8190b57cec5SDimitry Andric         case ConversionSpecifier::uArg:
8200b57cec5SDimitry Andric         case ConversionSpecifier::xArg:
8210b57cec5SDimitry Andric         case ConversionSpecifier::XArg:
8220b57cec5SDimitry Andric           return !Target.getTriple().isOSDarwin() &&
8230b57cec5SDimitry Andric                  !Target.getTriple().isOSWindows();
8240b57cec5SDimitry Andric         default:
8250b57cec5SDimitry Andric           return false;
8260b57cec5SDimitry Andric       }
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric     case LengthModifier::AsAllocate:
8290b57cec5SDimitry Andric       switch (CS.getKind()) {
8300b57cec5SDimitry Andric         case ConversionSpecifier::sArg:
8310b57cec5SDimitry Andric         case ConversionSpecifier::SArg:
8320b57cec5SDimitry Andric         case ConversionSpecifier::ScanListArg:
8330b57cec5SDimitry Andric           return true;
8340b57cec5SDimitry Andric         default:
8350b57cec5SDimitry Andric           return false;
8360b57cec5SDimitry Andric       }
8370b57cec5SDimitry Andric 
8380b57cec5SDimitry Andric     case LengthModifier::AsMAllocate:
8390b57cec5SDimitry Andric       switch (CS.getKind()) {
8400b57cec5SDimitry Andric         case ConversionSpecifier::cArg:
8410b57cec5SDimitry Andric         case ConversionSpecifier::CArg:
8420b57cec5SDimitry Andric         case ConversionSpecifier::sArg:
8430b57cec5SDimitry Andric         case ConversionSpecifier::SArg:
8440b57cec5SDimitry Andric         case ConversionSpecifier::ScanListArg:
8450b57cec5SDimitry Andric           return true;
8460b57cec5SDimitry Andric         default:
8470b57cec5SDimitry Andric           return false;
8480b57cec5SDimitry Andric       }
8490b57cec5SDimitry Andric     case LengthModifier::AsInt32:
8500b57cec5SDimitry Andric     case LengthModifier::AsInt3264:
8510b57cec5SDimitry Andric     case LengthModifier::AsInt64:
8520b57cec5SDimitry Andric       switch (CS.getKind()) {
8530b57cec5SDimitry Andric         case ConversionSpecifier::dArg:
8540b57cec5SDimitry Andric         case ConversionSpecifier::iArg:
8550b57cec5SDimitry Andric         case ConversionSpecifier::oArg:
8560b57cec5SDimitry Andric         case ConversionSpecifier::uArg:
8570b57cec5SDimitry Andric         case ConversionSpecifier::xArg:
8580b57cec5SDimitry Andric         case ConversionSpecifier::XArg:
8590b57cec5SDimitry Andric           return Target.getTriple().isOSMSVCRT();
8600b57cec5SDimitry Andric         default:
8610b57cec5SDimitry Andric           return false;
8620b57cec5SDimitry Andric       }
8630b57cec5SDimitry Andric     case LengthModifier::AsWide:
8640b57cec5SDimitry Andric       switch (CS.getKind()) {
8650b57cec5SDimitry Andric         case ConversionSpecifier::cArg:
8660b57cec5SDimitry Andric         case ConversionSpecifier::CArg:
8670b57cec5SDimitry Andric         case ConversionSpecifier::sArg:
8680b57cec5SDimitry Andric         case ConversionSpecifier::SArg:
8690b57cec5SDimitry Andric         case ConversionSpecifier::ZArg:
8700b57cec5SDimitry Andric           return Target.getTriple().isOSMSVCRT();
8710b57cec5SDimitry Andric         default:
8720b57cec5SDimitry Andric           return false;
8730b57cec5SDimitry Andric       }
8740b57cec5SDimitry Andric   }
8750b57cec5SDimitry Andric   llvm_unreachable("Invalid LengthModifier Kind!");
8760b57cec5SDimitry Andric }
8770b57cec5SDimitry Andric 
8780b57cec5SDimitry Andric bool FormatSpecifier::hasStandardLengthModifier() const {
8790b57cec5SDimitry Andric   switch (LM.getKind()) {
8800b57cec5SDimitry Andric     case LengthModifier::None:
8810b57cec5SDimitry Andric     case LengthModifier::AsChar:
8820b57cec5SDimitry Andric     case LengthModifier::AsShort:
8830b57cec5SDimitry Andric     case LengthModifier::AsLong:
8840b57cec5SDimitry Andric     case LengthModifier::AsLongLong:
8850b57cec5SDimitry Andric     case LengthModifier::AsIntMax:
8860b57cec5SDimitry Andric     case LengthModifier::AsSizeT:
8870b57cec5SDimitry Andric     case LengthModifier::AsPtrDiff:
8880b57cec5SDimitry Andric     case LengthModifier::AsLongDouble:
8890b57cec5SDimitry Andric       return true;
8900b57cec5SDimitry Andric     case LengthModifier::AsAllocate:
8910b57cec5SDimitry Andric     case LengthModifier::AsMAllocate:
8920b57cec5SDimitry Andric     case LengthModifier::AsQuad:
8930b57cec5SDimitry Andric     case LengthModifier::AsInt32:
8940b57cec5SDimitry Andric     case LengthModifier::AsInt3264:
8950b57cec5SDimitry Andric     case LengthModifier::AsInt64:
8960b57cec5SDimitry Andric     case LengthModifier::AsWide:
8970b57cec5SDimitry Andric     case LengthModifier::AsShortLong: // ???
8980b57cec5SDimitry Andric       return false;
8990b57cec5SDimitry Andric   }
9000b57cec5SDimitry Andric   llvm_unreachable("Invalid LengthModifier Kind!");
9010b57cec5SDimitry Andric }
9020b57cec5SDimitry Andric 
9030b57cec5SDimitry Andric bool FormatSpecifier::hasStandardConversionSpecifier(
9040b57cec5SDimitry Andric     const LangOptions &LangOpt) const {
9050b57cec5SDimitry Andric   switch (CS.getKind()) {
9060b57cec5SDimitry Andric     case ConversionSpecifier::cArg:
9070b57cec5SDimitry Andric     case ConversionSpecifier::dArg:
9080b57cec5SDimitry Andric     case ConversionSpecifier::iArg:
9090b57cec5SDimitry Andric     case ConversionSpecifier::oArg:
9100b57cec5SDimitry Andric     case ConversionSpecifier::uArg:
9110b57cec5SDimitry Andric     case ConversionSpecifier::xArg:
9120b57cec5SDimitry Andric     case ConversionSpecifier::XArg:
9130b57cec5SDimitry Andric     case ConversionSpecifier::fArg:
9140b57cec5SDimitry Andric     case ConversionSpecifier::FArg:
9150b57cec5SDimitry Andric     case ConversionSpecifier::eArg:
9160b57cec5SDimitry Andric     case ConversionSpecifier::EArg:
9170b57cec5SDimitry Andric     case ConversionSpecifier::gArg:
9180b57cec5SDimitry Andric     case ConversionSpecifier::GArg:
9190b57cec5SDimitry Andric     case ConversionSpecifier::aArg:
9200b57cec5SDimitry Andric     case ConversionSpecifier::AArg:
9210b57cec5SDimitry Andric     case ConversionSpecifier::sArg:
9220b57cec5SDimitry Andric     case ConversionSpecifier::pArg:
9230b57cec5SDimitry Andric     case ConversionSpecifier::nArg:
9240b57cec5SDimitry Andric     case ConversionSpecifier::ObjCObjArg:
9250b57cec5SDimitry Andric     case ConversionSpecifier::ScanListArg:
9260b57cec5SDimitry Andric     case ConversionSpecifier::PercentArg:
9270b57cec5SDimitry Andric     case ConversionSpecifier::PArg:
9280b57cec5SDimitry Andric       return true;
9290b57cec5SDimitry Andric     case ConversionSpecifier::CArg:
9300b57cec5SDimitry Andric     case ConversionSpecifier::SArg:
9310b57cec5SDimitry Andric       return LangOpt.ObjC;
9320b57cec5SDimitry Andric     case ConversionSpecifier::InvalidSpecifier:
9330b57cec5SDimitry Andric     case ConversionSpecifier::FreeBSDbArg:
9340b57cec5SDimitry Andric     case ConversionSpecifier::FreeBSDDArg:
9350b57cec5SDimitry Andric     case ConversionSpecifier::FreeBSDrArg:
9360b57cec5SDimitry Andric     case ConversionSpecifier::FreeBSDyArg:
9370b57cec5SDimitry Andric     case ConversionSpecifier::PrintErrno:
9380b57cec5SDimitry Andric     case ConversionSpecifier::DArg:
9390b57cec5SDimitry Andric     case ConversionSpecifier::OArg:
9400b57cec5SDimitry Andric     case ConversionSpecifier::UArg:
9410b57cec5SDimitry Andric     case ConversionSpecifier::ZArg:
9420b57cec5SDimitry Andric       return false;
9430b57cec5SDimitry Andric   }
9440b57cec5SDimitry Andric   llvm_unreachable("Invalid ConversionSpecifier Kind!");
9450b57cec5SDimitry Andric }
9460b57cec5SDimitry Andric 
9470b57cec5SDimitry Andric bool FormatSpecifier::hasStandardLengthConversionCombination() const {
9480b57cec5SDimitry Andric   if (LM.getKind() == LengthModifier::AsLongDouble) {
9490b57cec5SDimitry Andric     switch(CS.getKind()) {
9500b57cec5SDimitry Andric         case ConversionSpecifier::dArg:
9510b57cec5SDimitry Andric         case ConversionSpecifier::iArg:
9520b57cec5SDimitry Andric         case ConversionSpecifier::oArg:
9530b57cec5SDimitry Andric         case ConversionSpecifier::uArg:
9540b57cec5SDimitry Andric         case ConversionSpecifier::xArg:
9550b57cec5SDimitry Andric         case ConversionSpecifier::XArg:
9560b57cec5SDimitry Andric           return false;
9570b57cec5SDimitry Andric         default:
9580b57cec5SDimitry Andric           return true;
9590b57cec5SDimitry Andric     }
9600b57cec5SDimitry Andric   }
9610b57cec5SDimitry Andric   return true;
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const {
9650b57cec5SDimitry Andric   if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
9660b57cec5SDimitry Andric     if (LM.getKind() == LengthModifier::AsLongDouble ||
9670b57cec5SDimitry Andric         LM.getKind() == LengthModifier::AsQuad) {
9680b57cec5SDimitry Andric       LengthModifier FixedLM(LM);
9690b57cec5SDimitry Andric       FixedLM.setKind(LengthModifier::AsLongLong);
9700b57cec5SDimitry Andric       return FixedLM;
9710b57cec5SDimitry Andric     }
9720b57cec5SDimitry Andric   }
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric   return None;
9750b57cec5SDimitry Andric }
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,
9780b57cec5SDimitry Andric                                                 LengthModifier &LM) {
9790b57cec5SDimitry Andric   assert(isa<TypedefType>(QT) && "Expected a TypedefType");
9800b57cec5SDimitry Andric   const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();
9810b57cec5SDimitry Andric 
9820b57cec5SDimitry Andric   for (;;) {
9830b57cec5SDimitry Andric     const IdentifierInfo *Identifier = Typedef->getIdentifier();
9840b57cec5SDimitry Andric     if (Identifier->getName() == "size_t") {
9850b57cec5SDimitry Andric       LM.setKind(LengthModifier::AsSizeT);
9860b57cec5SDimitry Andric       return true;
9870b57cec5SDimitry Andric     } else if (Identifier->getName() == "ssize_t") {
9880b57cec5SDimitry Andric       // Not C99, but common in Unix.
9890b57cec5SDimitry Andric       LM.setKind(LengthModifier::AsSizeT);
9900b57cec5SDimitry Andric       return true;
9910b57cec5SDimitry Andric     } else if (Identifier->getName() == "intmax_t") {
9920b57cec5SDimitry Andric       LM.setKind(LengthModifier::AsIntMax);
9930b57cec5SDimitry Andric       return true;
9940b57cec5SDimitry Andric     } else if (Identifier->getName() == "uintmax_t") {
9950b57cec5SDimitry Andric       LM.setKind(LengthModifier::AsIntMax);
9960b57cec5SDimitry Andric       return true;
9970b57cec5SDimitry Andric     } else if (Identifier->getName() == "ptrdiff_t") {
9980b57cec5SDimitry Andric       LM.setKind(LengthModifier::AsPtrDiff);
9990b57cec5SDimitry Andric       return true;
10000b57cec5SDimitry Andric     }
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric     QualType T = Typedef->getUnderlyingType();
10030b57cec5SDimitry Andric     if (!isa<TypedefType>(T))
10040b57cec5SDimitry Andric       break;
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric     Typedef = cast<TypedefType>(T)->getDecl();
10070b57cec5SDimitry Andric   }
10080b57cec5SDimitry Andric   return false;
10090b57cec5SDimitry Andric }
1010