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: 362*a7dea167SDimitry 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: 390*a7dea167SDimitry Andric case BuiltinType::Bool: 391*a7dea167SDimitry Andric if (T == C.UnsignedShortTy || T == C.ShortTy) 392*a7dea167SDimitry 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::Void: 4230b57cec5SDimitry Andric case BuiltinType::Char_U: 4240b57cec5SDimitry Andric case BuiltinType::UChar: 4250b57cec5SDimitry Andric case BuiltinType::Char_S: 4260b57cec5SDimitry Andric case BuiltinType::SChar: 4270b57cec5SDimitry Andric return Match; 4280b57cec5SDimitry Andric default: 4290b57cec5SDimitry Andric break; 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric return NoMatch; 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric case WCStrTy: { 4360b57cec5SDimitry Andric const PointerType *PT = argTy->getAs<PointerType>(); 4370b57cec5SDimitry Andric if (!PT) 4380b57cec5SDimitry Andric return NoMatch; 4390b57cec5SDimitry Andric QualType pointeeTy = 4400b57cec5SDimitry Andric C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); 4410b57cec5SDimitry Andric return pointeeTy == C.getWideCharType() ? Match : NoMatch; 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric case WIntTy: { 4450b57cec5SDimitry Andric QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType(); 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt) 4480b57cec5SDimitry Andric return Match; 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric QualType PromoArg = argTy->isPromotableIntegerType() 4510b57cec5SDimitry Andric ? C.getPromotedIntegerType(argTy) 4520b57cec5SDimitry Andric : argTy; 4530b57cec5SDimitry Andric PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); 4540b57cec5SDimitry Andric 4550b57cec5SDimitry Andric // If the promoted argument is the corresponding signed type of the 4560b57cec5SDimitry Andric // wint_t type, then it should match. 4570b57cec5SDimitry Andric if (PromoArg->hasSignedIntegerRepresentation() && 4580b57cec5SDimitry Andric C.getCorrespondingUnsignedType(PromoArg) == WInt) 4590b57cec5SDimitry Andric return Match; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric return WInt == PromoArg ? Match : NoMatch; 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric case CPointerTy: 4650b57cec5SDimitry Andric if (argTy->isVoidPointerType()) { 4660b57cec5SDimitry Andric return Match; 4670b57cec5SDimitry Andric } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() || 4680b57cec5SDimitry Andric argTy->isBlockPointerType() || argTy->isNullPtrType()) { 4690b57cec5SDimitry Andric return NoMatchPedantic; 4700b57cec5SDimitry Andric } else { 4710b57cec5SDimitry Andric return NoMatch; 4720b57cec5SDimitry Andric } 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric case ObjCPointerTy: { 4750b57cec5SDimitry Andric if (argTy->getAs<ObjCObjectPointerType>() || 4760b57cec5SDimitry Andric argTy->getAs<BlockPointerType>()) 4770b57cec5SDimitry Andric return Match; 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric // Handle implicit toll-free bridging. 4800b57cec5SDimitry Andric if (const PointerType *PT = argTy->getAs<PointerType>()) { 4810b57cec5SDimitry Andric // Things such as CFTypeRef are really just opaque pointers 4820b57cec5SDimitry Andric // to C structs representing CF types that can often be bridged 4830b57cec5SDimitry Andric // to Objective-C objects. Since the compiler doesn't know which 4840b57cec5SDimitry Andric // structs can be toll-free bridged, we just accept them all. 4850b57cec5SDimitry Andric QualType pointee = PT->getPointeeType(); 4860b57cec5SDimitry Andric if (pointee->getAsStructureType() || pointee->isVoidType()) 4870b57cec5SDimitry Andric return Match; 4880b57cec5SDimitry Andric } 4890b57cec5SDimitry Andric return NoMatch; 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric } 4920b57cec5SDimitry Andric 4930b57cec5SDimitry Andric llvm_unreachable("Invalid ArgType Kind!"); 4940b57cec5SDimitry Andric } 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const { 4970b57cec5SDimitry Andric // Check for valid vector element types. 4980b57cec5SDimitry Andric if (T.isNull()) 4990b57cec5SDimitry Andric return ArgType::Invalid(); 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric QualType Vec = C.getExtVectorType(T, NumElts); 5020b57cec5SDimitry Andric return ArgType(Vec, Name); 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric QualType ArgType::getRepresentativeType(ASTContext &C) const { 5060b57cec5SDimitry Andric QualType Res; 5070b57cec5SDimitry Andric switch (K) { 5080b57cec5SDimitry Andric case InvalidTy: 5090b57cec5SDimitry Andric llvm_unreachable("No representative type for Invalid ArgType"); 5100b57cec5SDimitry Andric case UnknownTy: 5110b57cec5SDimitry Andric llvm_unreachable("No representative type for Unknown ArgType"); 5120b57cec5SDimitry Andric case AnyCharTy: 5130b57cec5SDimitry Andric Res = C.CharTy; 5140b57cec5SDimitry Andric break; 5150b57cec5SDimitry Andric case SpecificTy: 5160b57cec5SDimitry Andric Res = T; 5170b57cec5SDimitry Andric break; 5180b57cec5SDimitry Andric case CStrTy: 5190b57cec5SDimitry Andric Res = C.getPointerType(C.CharTy); 5200b57cec5SDimitry Andric break; 5210b57cec5SDimitry Andric case WCStrTy: 5220b57cec5SDimitry Andric Res = C.getPointerType(C.getWideCharType()); 5230b57cec5SDimitry Andric break; 5240b57cec5SDimitry Andric case ObjCPointerTy: 5250b57cec5SDimitry Andric Res = C.ObjCBuiltinIdTy; 5260b57cec5SDimitry Andric break; 5270b57cec5SDimitry Andric case CPointerTy: 5280b57cec5SDimitry Andric Res = C.VoidPtrTy; 5290b57cec5SDimitry Andric break; 5300b57cec5SDimitry Andric case WIntTy: { 5310b57cec5SDimitry Andric Res = C.getWIntType(); 5320b57cec5SDimitry Andric break; 5330b57cec5SDimitry Andric } 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric if (Ptr) 5370b57cec5SDimitry Andric Res = C.getPointerType(Res); 5380b57cec5SDimitry Andric return Res; 5390b57cec5SDimitry Andric } 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric std::string ArgType::getRepresentativeTypeName(ASTContext &C) const { 5420b57cec5SDimitry Andric std::string S = getRepresentativeType(C).getAsString(); 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric std::string Alias; 5450b57cec5SDimitry Andric if (Name) { 5460b57cec5SDimitry Andric // Use a specific name for this type, e.g. "size_t". 5470b57cec5SDimitry Andric Alias = Name; 5480b57cec5SDimitry Andric if (Ptr) { 5490b57cec5SDimitry Andric // If ArgType is actually a pointer to T, append an asterisk. 5500b57cec5SDimitry Andric Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *"; 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric // If Alias is the same as the underlying type, e.g. wchar_t, then drop it. 5530b57cec5SDimitry Andric if (S == Alias) 5540b57cec5SDimitry Andric Alias.clear(); 5550b57cec5SDimitry Andric } 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric if (!Alias.empty()) 5580b57cec5SDimitry Andric return std::string("'") + Alias + "' (aka '" + S + "')"; 5590b57cec5SDimitry Andric return std::string("'") + S + "'"; 5600b57cec5SDimitry Andric } 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5640b57cec5SDimitry Andric // Methods on OptionalAmount. 5650b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5660b57cec5SDimitry Andric 5670b57cec5SDimitry Andric ArgType 5680b57cec5SDimitry Andric analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const { 5690b57cec5SDimitry Andric return Ctx.IntTy; 5700b57cec5SDimitry Andric } 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5730b57cec5SDimitry Andric // Methods on LengthModifier. 5740b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric const char * 5770b57cec5SDimitry Andric analyze_format_string::LengthModifier::toString() const { 5780b57cec5SDimitry Andric switch (kind) { 5790b57cec5SDimitry Andric case AsChar: 5800b57cec5SDimitry Andric return "hh"; 5810b57cec5SDimitry Andric case AsShort: 5820b57cec5SDimitry Andric return "h"; 5830b57cec5SDimitry Andric case AsShortLong: 5840b57cec5SDimitry Andric return "hl"; 5850b57cec5SDimitry Andric case AsLong: // or AsWideChar 5860b57cec5SDimitry Andric return "l"; 5870b57cec5SDimitry Andric case AsLongLong: 5880b57cec5SDimitry Andric return "ll"; 5890b57cec5SDimitry Andric case AsQuad: 5900b57cec5SDimitry Andric return "q"; 5910b57cec5SDimitry Andric case AsIntMax: 5920b57cec5SDimitry Andric return "j"; 5930b57cec5SDimitry Andric case AsSizeT: 5940b57cec5SDimitry Andric return "z"; 5950b57cec5SDimitry Andric case AsPtrDiff: 5960b57cec5SDimitry Andric return "t"; 5970b57cec5SDimitry Andric case AsInt32: 5980b57cec5SDimitry Andric return "I32"; 5990b57cec5SDimitry Andric case AsInt3264: 6000b57cec5SDimitry Andric return "I"; 6010b57cec5SDimitry Andric case AsInt64: 6020b57cec5SDimitry Andric return "I64"; 6030b57cec5SDimitry Andric case AsLongDouble: 6040b57cec5SDimitry Andric return "L"; 6050b57cec5SDimitry Andric case AsAllocate: 6060b57cec5SDimitry Andric return "a"; 6070b57cec5SDimitry Andric case AsMAllocate: 6080b57cec5SDimitry Andric return "m"; 6090b57cec5SDimitry Andric case AsWide: 6100b57cec5SDimitry Andric return "w"; 6110b57cec5SDimitry Andric case None: 6120b57cec5SDimitry Andric return ""; 6130b57cec5SDimitry Andric } 6140b57cec5SDimitry Andric return nullptr; 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6180b57cec5SDimitry Andric // Methods on ConversionSpecifier. 6190b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric const char *ConversionSpecifier::toString() const { 6220b57cec5SDimitry Andric switch (kind) { 6230b57cec5SDimitry Andric case dArg: return "d"; 6240b57cec5SDimitry Andric case DArg: return "D"; 6250b57cec5SDimitry Andric case iArg: return "i"; 6260b57cec5SDimitry Andric case oArg: return "o"; 6270b57cec5SDimitry Andric case OArg: return "O"; 6280b57cec5SDimitry Andric case uArg: return "u"; 6290b57cec5SDimitry Andric case UArg: return "U"; 6300b57cec5SDimitry Andric case xArg: return "x"; 6310b57cec5SDimitry Andric case XArg: return "X"; 6320b57cec5SDimitry Andric case fArg: return "f"; 6330b57cec5SDimitry Andric case FArg: return "F"; 6340b57cec5SDimitry Andric case eArg: return "e"; 6350b57cec5SDimitry Andric case EArg: return "E"; 6360b57cec5SDimitry Andric case gArg: return "g"; 6370b57cec5SDimitry Andric case GArg: return "G"; 6380b57cec5SDimitry Andric case aArg: return "a"; 6390b57cec5SDimitry Andric case AArg: return "A"; 6400b57cec5SDimitry Andric case cArg: return "c"; 6410b57cec5SDimitry Andric case sArg: return "s"; 6420b57cec5SDimitry Andric case pArg: return "p"; 6430b57cec5SDimitry Andric case PArg: 6440b57cec5SDimitry Andric return "P"; 6450b57cec5SDimitry Andric case nArg: return "n"; 6460b57cec5SDimitry Andric case PercentArg: return "%"; 6470b57cec5SDimitry Andric case ScanListArg: return "["; 6480b57cec5SDimitry Andric case InvalidSpecifier: return nullptr; 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric // POSIX unicode extensions. 6510b57cec5SDimitry Andric case CArg: return "C"; 6520b57cec5SDimitry Andric case SArg: return "S"; 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric // Objective-C specific specifiers. 6550b57cec5SDimitry Andric case ObjCObjArg: return "@"; 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric // FreeBSD kernel specific specifiers. 6580b57cec5SDimitry Andric case FreeBSDbArg: return "b"; 6590b57cec5SDimitry Andric case FreeBSDDArg: return "D"; 6600b57cec5SDimitry Andric case FreeBSDrArg: return "r"; 6610b57cec5SDimitry Andric case FreeBSDyArg: return "y"; 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric // GlibC specific specifiers. 6640b57cec5SDimitry Andric case PrintErrno: return "m"; 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric // MS specific specifiers. 6670b57cec5SDimitry Andric case ZArg: return "Z"; 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric return nullptr; 6700b57cec5SDimitry Andric } 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric Optional<ConversionSpecifier> 6730b57cec5SDimitry Andric ConversionSpecifier::getStandardSpecifier() const { 6740b57cec5SDimitry Andric ConversionSpecifier::Kind NewKind; 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric switch (getKind()) { 6770b57cec5SDimitry Andric default: 6780b57cec5SDimitry Andric return None; 6790b57cec5SDimitry Andric case DArg: 6800b57cec5SDimitry Andric NewKind = dArg; 6810b57cec5SDimitry Andric break; 6820b57cec5SDimitry Andric case UArg: 6830b57cec5SDimitry Andric NewKind = uArg; 6840b57cec5SDimitry Andric break; 6850b57cec5SDimitry Andric case OArg: 6860b57cec5SDimitry Andric NewKind = oArg; 6870b57cec5SDimitry Andric break; 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric ConversionSpecifier FixedCS(*this); 6910b57cec5SDimitry Andric FixedCS.setKind(NewKind); 6920b57cec5SDimitry Andric return FixedCS; 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6960b57cec5SDimitry Andric // Methods on OptionalAmount. 6970b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric void OptionalAmount::toString(raw_ostream &os) const { 7000b57cec5SDimitry Andric switch (hs) { 7010b57cec5SDimitry Andric case Invalid: 7020b57cec5SDimitry Andric case NotSpecified: 7030b57cec5SDimitry Andric return; 7040b57cec5SDimitry Andric case Arg: 7050b57cec5SDimitry Andric if (UsesDotPrefix) 7060b57cec5SDimitry Andric os << "."; 7070b57cec5SDimitry Andric if (usesPositionalArg()) 7080b57cec5SDimitry Andric os << "*" << getPositionalArgIndex() << "$"; 7090b57cec5SDimitry Andric else 7100b57cec5SDimitry Andric os << "*"; 7110b57cec5SDimitry Andric break; 7120b57cec5SDimitry Andric case Constant: 7130b57cec5SDimitry Andric if (UsesDotPrefix) 7140b57cec5SDimitry Andric os << "."; 7150b57cec5SDimitry Andric os << amt; 7160b57cec5SDimitry Andric break; 7170b57cec5SDimitry Andric } 7180b57cec5SDimitry Andric } 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, 7210b57cec5SDimitry Andric const LangOptions &LO) const { 7220b57cec5SDimitry Andric switch (LM.getKind()) { 7230b57cec5SDimitry Andric case LengthModifier::None: 7240b57cec5SDimitry Andric return true; 7250b57cec5SDimitry Andric 7260b57cec5SDimitry Andric // Handle most integer flags 7270b57cec5SDimitry Andric case LengthModifier::AsShort: 7280b57cec5SDimitry Andric // Length modifier only applies to FP vectors. 7290b57cec5SDimitry Andric if (LO.OpenCL && CS.isDoubleArg()) 7300b57cec5SDimitry Andric return !VectorNumElts.isInvalid(); 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric if (Target.getTriple().isOSMSVCRT()) { 7330b57cec5SDimitry Andric switch (CS.getKind()) { 7340b57cec5SDimitry Andric case ConversionSpecifier::cArg: 7350b57cec5SDimitry Andric case ConversionSpecifier::CArg: 7360b57cec5SDimitry Andric case ConversionSpecifier::sArg: 7370b57cec5SDimitry Andric case ConversionSpecifier::SArg: 7380b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 7390b57cec5SDimitry Andric return true; 7400b57cec5SDimitry Andric default: 7410b57cec5SDimitry Andric break; 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric } 7440b57cec5SDimitry Andric LLVM_FALLTHROUGH; 7450b57cec5SDimitry Andric case LengthModifier::AsChar: 7460b57cec5SDimitry Andric case LengthModifier::AsLongLong: 7470b57cec5SDimitry Andric case LengthModifier::AsQuad: 7480b57cec5SDimitry Andric case LengthModifier::AsIntMax: 7490b57cec5SDimitry Andric case LengthModifier::AsSizeT: 7500b57cec5SDimitry Andric case LengthModifier::AsPtrDiff: 7510b57cec5SDimitry Andric switch (CS.getKind()) { 7520b57cec5SDimitry Andric case ConversionSpecifier::dArg: 7530b57cec5SDimitry Andric case ConversionSpecifier::DArg: 7540b57cec5SDimitry Andric case ConversionSpecifier::iArg: 7550b57cec5SDimitry Andric case ConversionSpecifier::oArg: 7560b57cec5SDimitry Andric case ConversionSpecifier::OArg: 7570b57cec5SDimitry Andric case ConversionSpecifier::uArg: 7580b57cec5SDimitry Andric case ConversionSpecifier::UArg: 7590b57cec5SDimitry Andric case ConversionSpecifier::xArg: 7600b57cec5SDimitry Andric case ConversionSpecifier::XArg: 7610b57cec5SDimitry Andric case ConversionSpecifier::nArg: 7620b57cec5SDimitry Andric return true; 7630b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDrArg: 7640b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDyArg: 7650b57cec5SDimitry Andric return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); 7660b57cec5SDimitry Andric default: 7670b57cec5SDimitry Andric return false; 7680b57cec5SDimitry Andric } 7690b57cec5SDimitry Andric 7700b57cec5SDimitry Andric case LengthModifier::AsShortLong: 7710b57cec5SDimitry Andric return LO.OpenCL && !VectorNumElts.isInvalid(); 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric // Handle 'l' flag 7740b57cec5SDimitry Andric case LengthModifier::AsLong: // or AsWideChar 7750b57cec5SDimitry Andric if (CS.isDoubleArg()) { 7760b57cec5SDimitry Andric // Invalid for OpenCL FP scalars. 7770b57cec5SDimitry Andric if (LO.OpenCL && VectorNumElts.isInvalid()) 7780b57cec5SDimitry Andric return false; 7790b57cec5SDimitry Andric return true; 7800b57cec5SDimitry Andric } 7810b57cec5SDimitry Andric 7820b57cec5SDimitry Andric switch (CS.getKind()) { 7830b57cec5SDimitry Andric case ConversionSpecifier::dArg: 7840b57cec5SDimitry Andric case ConversionSpecifier::DArg: 7850b57cec5SDimitry Andric case ConversionSpecifier::iArg: 7860b57cec5SDimitry Andric case ConversionSpecifier::oArg: 7870b57cec5SDimitry Andric case ConversionSpecifier::OArg: 7880b57cec5SDimitry Andric case ConversionSpecifier::uArg: 7890b57cec5SDimitry Andric case ConversionSpecifier::UArg: 7900b57cec5SDimitry Andric case ConversionSpecifier::xArg: 7910b57cec5SDimitry Andric case ConversionSpecifier::XArg: 7920b57cec5SDimitry Andric case ConversionSpecifier::nArg: 7930b57cec5SDimitry Andric case ConversionSpecifier::cArg: 7940b57cec5SDimitry Andric case ConversionSpecifier::sArg: 7950b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 7960b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 7970b57cec5SDimitry Andric return true; 7980b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDrArg: 7990b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDyArg: 8000b57cec5SDimitry Andric return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); 8010b57cec5SDimitry Andric default: 8020b57cec5SDimitry Andric return false; 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric case LengthModifier::AsLongDouble: 8060b57cec5SDimitry Andric switch (CS.getKind()) { 8070b57cec5SDimitry Andric case ConversionSpecifier::aArg: 8080b57cec5SDimitry Andric case ConversionSpecifier::AArg: 8090b57cec5SDimitry Andric case ConversionSpecifier::fArg: 8100b57cec5SDimitry Andric case ConversionSpecifier::FArg: 8110b57cec5SDimitry Andric case ConversionSpecifier::eArg: 8120b57cec5SDimitry Andric case ConversionSpecifier::EArg: 8130b57cec5SDimitry Andric case ConversionSpecifier::gArg: 8140b57cec5SDimitry Andric case ConversionSpecifier::GArg: 8150b57cec5SDimitry Andric return true; 8160b57cec5SDimitry Andric // GNU libc extension. 8170b57cec5SDimitry Andric case ConversionSpecifier::dArg: 8180b57cec5SDimitry Andric case ConversionSpecifier::iArg: 8190b57cec5SDimitry Andric case ConversionSpecifier::oArg: 8200b57cec5SDimitry Andric case ConversionSpecifier::uArg: 8210b57cec5SDimitry Andric case ConversionSpecifier::xArg: 8220b57cec5SDimitry Andric case ConversionSpecifier::XArg: 8230b57cec5SDimitry Andric return !Target.getTriple().isOSDarwin() && 8240b57cec5SDimitry Andric !Target.getTriple().isOSWindows(); 8250b57cec5SDimitry Andric default: 8260b57cec5SDimitry Andric return false; 8270b57cec5SDimitry Andric } 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric case LengthModifier::AsAllocate: 8300b57cec5SDimitry Andric switch (CS.getKind()) { 8310b57cec5SDimitry Andric case ConversionSpecifier::sArg: 8320b57cec5SDimitry Andric case ConversionSpecifier::SArg: 8330b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 8340b57cec5SDimitry Andric return true; 8350b57cec5SDimitry Andric default: 8360b57cec5SDimitry Andric return false; 8370b57cec5SDimitry Andric } 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric case LengthModifier::AsMAllocate: 8400b57cec5SDimitry Andric switch (CS.getKind()) { 8410b57cec5SDimitry Andric case ConversionSpecifier::cArg: 8420b57cec5SDimitry Andric case ConversionSpecifier::CArg: 8430b57cec5SDimitry Andric case ConversionSpecifier::sArg: 8440b57cec5SDimitry Andric case ConversionSpecifier::SArg: 8450b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 8460b57cec5SDimitry Andric return true; 8470b57cec5SDimitry Andric default: 8480b57cec5SDimitry Andric return false; 8490b57cec5SDimitry Andric } 8500b57cec5SDimitry Andric case LengthModifier::AsInt32: 8510b57cec5SDimitry Andric case LengthModifier::AsInt3264: 8520b57cec5SDimitry Andric case LengthModifier::AsInt64: 8530b57cec5SDimitry Andric switch (CS.getKind()) { 8540b57cec5SDimitry Andric case ConversionSpecifier::dArg: 8550b57cec5SDimitry Andric case ConversionSpecifier::iArg: 8560b57cec5SDimitry Andric case ConversionSpecifier::oArg: 8570b57cec5SDimitry Andric case ConversionSpecifier::uArg: 8580b57cec5SDimitry Andric case ConversionSpecifier::xArg: 8590b57cec5SDimitry Andric case ConversionSpecifier::XArg: 8600b57cec5SDimitry Andric return Target.getTriple().isOSMSVCRT(); 8610b57cec5SDimitry Andric default: 8620b57cec5SDimitry Andric return false; 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric case LengthModifier::AsWide: 8650b57cec5SDimitry Andric switch (CS.getKind()) { 8660b57cec5SDimitry Andric case ConversionSpecifier::cArg: 8670b57cec5SDimitry Andric case ConversionSpecifier::CArg: 8680b57cec5SDimitry Andric case ConversionSpecifier::sArg: 8690b57cec5SDimitry Andric case ConversionSpecifier::SArg: 8700b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 8710b57cec5SDimitry Andric return Target.getTriple().isOSMSVCRT(); 8720b57cec5SDimitry Andric default: 8730b57cec5SDimitry Andric return false; 8740b57cec5SDimitry Andric } 8750b57cec5SDimitry Andric } 8760b57cec5SDimitry Andric llvm_unreachable("Invalid LengthModifier Kind!"); 8770b57cec5SDimitry Andric } 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric bool FormatSpecifier::hasStandardLengthModifier() const { 8800b57cec5SDimitry Andric switch (LM.getKind()) { 8810b57cec5SDimitry Andric case LengthModifier::None: 8820b57cec5SDimitry Andric case LengthModifier::AsChar: 8830b57cec5SDimitry Andric case LengthModifier::AsShort: 8840b57cec5SDimitry Andric case LengthModifier::AsLong: 8850b57cec5SDimitry Andric case LengthModifier::AsLongLong: 8860b57cec5SDimitry Andric case LengthModifier::AsIntMax: 8870b57cec5SDimitry Andric case LengthModifier::AsSizeT: 8880b57cec5SDimitry Andric case LengthModifier::AsPtrDiff: 8890b57cec5SDimitry Andric case LengthModifier::AsLongDouble: 8900b57cec5SDimitry Andric return true; 8910b57cec5SDimitry Andric case LengthModifier::AsAllocate: 8920b57cec5SDimitry Andric case LengthModifier::AsMAllocate: 8930b57cec5SDimitry Andric case LengthModifier::AsQuad: 8940b57cec5SDimitry Andric case LengthModifier::AsInt32: 8950b57cec5SDimitry Andric case LengthModifier::AsInt3264: 8960b57cec5SDimitry Andric case LengthModifier::AsInt64: 8970b57cec5SDimitry Andric case LengthModifier::AsWide: 8980b57cec5SDimitry Andric case LengthModifier::AsShortLong: // ??? 8990b57cec5SDimitry Andric return false; 9000b57cec5SDimitry Andric } 9010b57cec5SDimitry Andric llvm_unreachable("Invalid LengthModifier Kind!"); 9020b57cec5SDimitry Andric } 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric bool FormatSpecifier::hasStandardConversionSpecifier( 9050b57cec5SDimitry Andric const LangOptions &LangOpt) const { 9060b57cec5SDimitry Andric switch (CS.getKind()) { 9070b57cec5SDimitry Andric case ConversionSpecifier::cArg: 9080b57cec5SDimitry Andric case ConversionSpecifier::dArg: 9090b57cec5SDimitry Andric case ConversionSpecifier::iArg: 9100b57cec5SDimitry Andric case ConversionSpecifier::oArg: 9110b57cec5SDimitry Andric case ConversionSpecifier::uArg: 9120b57cec5SDimitry Andric case ConversionSpecifier::xArg: 9130b57cec5SDimitry Andric case ConversionSpecifier::XArg: 9140b57cec5SDimitry Andric case ConversionSpecifier::fArg: 9150b57cec5SDimitry Andric case ConversionSpecifier::FArg: 9160b57cec5SDimitry Andric case ConversionSpecifier::eArg: 9170b57cec5SDimitry Andric case ConversionSpecifier::EArg: 9180b57cec5SDimitry Andric case ConversionSpecifier::gArg: 9190b57cec5SDimitry Andric case ConversionSpecifier::GArg: 9200b57cec5SDimitry Andric case ConversionSpecifier::aArg: 9210b57cec5SDimitry Andric case ConversionSpecifier::AArg: 9220b57cec5SDimitry Andric case ConversionSpecifier::sArg: 9230b57cec5SDimitry Andric case ConversionSpecifier::pArg: 9240b57cec5SDimitry Andric case ConversionSpecifier::nArg: 9250b57cec5SDimitry Andric case ConversionSpecifier::ObjCObjArg: 9260b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 9270b57cec5SDimitry Andric case ConversionSpecifier::PercentArg: 9280b57cec5SDimitry Andric case ConversionSpecifier::PArg: 9290b57cec5SDimitry Andric return true; 9300b57cec5SDimitry Andric case ConversionSpecifier::CArg: 9310b57cec5SDimitry Andric case ConversionSpecifier::SArg: 9320b57cec5SDimitry Andric return LangOpt.ObjC; 9330b57cec5SDimitry Andric case ConversionSpecifier::InvalidSpecifier: 9340b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDbArg: 9350b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDDArg: 9360b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDrArg: 9370b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDyArg: 9380b57cec5SDimitry Andric case ConversionSpecifier::PrintErrno: 9390b57cec5SDimitry Andric case ConversionSpecifier::DArg: 9400b57cec5SDimitry Andric case ConversionSpecifier::OArg: 9410b57cec5SDimitry Andric case ConversionSpecifier::UArg: 9420b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 9430b57cec5SDimitry Andric return false; 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric llvm_unreachable("Invalid ConversionSpecifier Kind!"); 9460b57cec5SDimitry Andric } 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric bool FormatSpecifier::hasStandardLengthConversionCombination() const { 9490b57cec5SDimitry Andric if (LM.getKind() == LengthModifier::AsLongDouble) { 9500b57cec5SDimitry Andric switch(CS.getKind()) { 9510b57cec5SDimitry Andric case ConversionSpecifier::dArg: 9520b57cec5SDimitry Andric case ConversionSpecifier::iArg: 9530b57cec5SDimitry Andric case ConversionSpecifier::oArg: 9540b57cec5SDimitry Andric case ConversionSpecifier::uArg: 9550b57cec5SDimitry Andric case ConversionSpecifier::xArg: 9560b57cec5SDimitry Andric case ConversionSpecifier::XArg: 9570b57cec5SDimitry Andric return false; 9580b57cec5SDimitry Andric default: 9590b57cec5SDimitry Andric return true; 9600b57cec5SDimitry Andric } 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric return true; 9630b57cec5SDimitry Andric } 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const { 9660b57cec5SDimitry Andric if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) { 9670b57cec5SDimitry Andric if (LM.getKind() == LengthModifier::AsLongDouble || 9680b57cec5SDimitry Andric LM.getKind() == LengthModifier::AsQuad) { 9690b57cec5SDimitry Andric LengthModifier FixedLM(LM); 9700b57cec5SDimitry Andric FixedLM.setKind(LengthModifier::AsLongLong); 9710b57cec5SDimitry Andric return FixedLM; 9720b57cec5SDimitry Andric } 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric return None; 9760b57cec5SDimitry Andric } 9770b57cec5SDimitry Andric 9780b57cec5SDimitry Andric bool FormatSpecifier::namedTypeToLengthModifier(QualType QT, 9790b57cec5SDimitry Andric LengthModifier &LM) { 9800b57cec5SDimitry Andric assert(isa<TypedefType>(QT) && "Expected a TypedefType"); 9810b57cec5SDimitry Andric const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl(); 9820b57cec5SDimitry Andric 9830b57cec5SDimitry Andric for (;;) { 9840b57cec5SDimitry Andric const IdentifierInfo *Identifier = Typedef->getIdentifier(); 9850b57cec5SDimitry Andric if (Identifier->getName() == "size_t") { 9860b57cec5SDimitry Andric LM.setKind(LengthModifier::AsSizeT); 9870b57cec5SDimitry Andric return true; 9880b57cec5SDimitry Andric } else if (Identifier->getName() == "ssize_t") { 9890b57cec5SDimitry Andric // Not C99, but common in Unix. 9900b57cec5SDimitry Andric LM.setKind(LengthModifier::AsSizeT); 9910b57cec5SDimitry Andric return true; 9920b57cec5SDimitry Andric } else if (Identifier->getName() == "intmax_t") { 9930b57cec5SDimitry Andric LM.setKind(LengthModifier::AsIntMax); 9940b57cec5SDimitry Andric return true; 9950b57cec5SDimitry Andric } else if (Identifier->getName() == "uintmax_t") { 9960b57cec5SDimitry Andric LM.setKind(LengthModifier::AsIntMax); 9970b57cec5SDimitry Andric return true; 9980b57cec5SDimitry Andric } else if (Identifier->getName() == "ptrdiff_t") { 9990b57cec5SDimitry Andric LM.setKind(LengthModifier::AsPtrDiff); 10000b57cec5SDimitry Andric return true; 10010b57cec5SDimitry Andric } 10020b57cec5SDimitry Andric 10030b57cec5SDimitry Andric QualType T = Typedef->getUnderlyingType(); 10040b57cec5SDimitry Andric if (!isa<TypedefType>(T)) 10050b57cec5SDimitry Andric break; 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric Typedef = cast<TypedefType>(T)->getDecl(); 10080b57cec5SDimitry Andric } 10090b57cec5SDimitry Andric return false; 10100b57cec5SDimitry Andric } 1011