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" 18bdd1243dSDimitry Andric #include <optional> 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric using clang::analyze_format_string::ArgType; 210b57cec5SDimitry Andric using clang::analyze_format_string::FormatStringHandler; 220b57cec5SDimitry Andric using clang::analyze_format_string::FormatSpecifier; 230b57cec5SDimitry Andric using clang::analyze_format_string::LengthModifier; 240b57cec5SDimitry Andric using clang::analyze_format_string::OptionalAmount; 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 { 325753f127fSDimitry Andric // When using the format attribute in C++, you can receive a function or an 326753f127fSDimitry Andric // array that will necessarily decay to a pointer when passed to the final 327753f127fSDimitry Andric // format consumer. Apply decay before type comparison. 328753f127fSDimitry Andric if (argTy->canDecayToPointerType()) 329753f127fSDimitry Andric argTy = C.getDecayedType(argTy); 330753f127fSDimitry Andric 3310b57cec5SDimitry Andric if (Ptr) { 3320b57cec5SDimitry Andric // It has to be a pointer. 3330b57cec5SDimitry Andric const PointerType *PT = argTy->getAs<PointerType>(); 3340b57cec5SDimitry Andric if (!PT) 3350b57cec5SDimitry Andric return NoMatch; 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric // We cannot write through a const qualified pointer. 3380b57cec5SDimitry Andric if (PT->getPointeeType().isConstQualified()) 3390b57cec5SDimitry Andric return NoMatch; 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric argTy = PT->getPointeeType(); 3420b57cec5SDimitry Andric } 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric switch (K) { 3450b57cec5SDimitry Andric case InvalidTy: 3460b57cec5SDimitry Andric llvm_unreachable("ArgType must be valid"); 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric case UnknownTy: 3490b57cec5SDimitry Andric return Match; 3500b57cec5SDimitry Andric 3510b57cec5SDimitry Andric case AnyCharTy: { 352bdd1243dSDimitry Andric if (const auto *ETy = argTy->getAs<EnumType>()) { 3530b57cec5SDimitry Andric // If the enum is incomplete we know nothing about the underlying type. 35406c3fb27SDimitry Andric // Assume that it's 'int'. Do not use the underlying type for a scoped 35506c3fb27SDimitry Andric // enumeration. 3560b57cec5SDimitry Andric if (!ETy->getDecl()->isComplete()) 3570b57cec5SDimitry Andric return NoMatch; 35806c3fb27SDimitry Andric if (ETy->isUnscopedEnumerationType()) 3590b57cec5SDimitry Andric argTy = ETy->getDecl()->getIntegerType(); 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric 362bdd1243dSDimitry Andric if (const auto *BT = argTy->getAs<BuiltinType>()) { 363bdd1243dSDimitry Andric // The types are perfectly matched? 3640b57cec5SDimitry Andric switch (BT->getKind()) { 3650b57cec5SDimitry Andric default: 3660b57cec5SDimitry Andric break; 3670b57cec5SDimitry Andric case BuiltinType::Char_S: 3680b57cec5SDimitry Andric case BuiltinType::SChar: 3690b57cec5SDimitry Andric case BuiltinType::UChar: 3700b57cec5SDimitry Andric case BuiltinType::Char_U: 3710b57cec5SDimitry Andric return Match; 3725f757f3fSDimitry Andric case BuiltinType::Bool: 3735f757f3fSDimitry Andric if (!Ptr) 3745f757f3fSDimitry Andric return Match; 3755f757f3fSDimitry Andric break; 3760b57cec5SDimitry Andric } 377bdd1243dSDimitry Andric // "Partially matched" because of promotions? 378bdd1243dSDimitry Andric if (!Ptr) { 379bdd1243dSDimitry Andric switch (BT->getKind()) { 380bdd1243dSDimitry Andric default: 381bdd1243dSDimitry Andric break; 382bdd1243dSDimitry Andric case BuiltinType::Int: 383bdd1243dSDimitry Andric case BuiltinType::UInt: 384bdd1243dSDimitry Andric return MatchPromotion; 385bdd1243dSDimitry Andric case BuiltinType::Short: 386bdd1243dSDimitry Andric case BuiltinType::UShort: 387bdd1243dSDimitry Andric case BuiltinType::WChar_S: 388bdd1243dSDimitry Andric case BuiltinType::WChar_U: 389bdd1243dSDimitry Andric return NoMatchPromotionTypeConfusion; 390bdd1243dSDimitry Andric } 391bdd1243dSDimitry Andric } 392bdd1243dSDimitry Andric } 3930b57cec5SDimitry Andric return NoMatch; 3940b57cec5SDimitry Andric } 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric case SpecificTy: { 3970b57cec5SDimitry Andric if (const EnumType *ETy = argTy->getAs<EnumType>()) { 3980b57cec5SDimitry Andric // If the enum is incomplete we know nothing about the underlying type. 39906c3fb27SDimitry Andric // Assume that it's 'int'. Do not use the underlying type for a scoped 40006c3fb27SDimitry Andric // enumeration as that needs an exact match. 4010b57cec5SDimitry Andric if (!ETy->getDecl()->isComplete()) 4020b57cec5SDimitry Andric argTy = C.IntTy; 40306c3fb27SDimitry Andric else if (ETy->isUnscopedEnumerationType()) 4040b57cec5SDimitry Andric argTy = ETy->getDecl()->getIntegerType(); 4050b57cec5SDimitry Andric } 406*0fca6ea1SDimitry Andric 407*0fca6ea1SDimitry Andric if (argTy->isSaturatedFixedPointType()) 408*0fca6ea1SDimitry Andric argTy = C.getCorrespondingUnsaturatedType(argTy); 409*0fca6ea1SDimitry Andric 4100b57cec5SDimitry Andric argTy = C.getCanonicalType(argTy).getUnqualifiedType(); 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric if (T == argTy) 4130b57cec5SDimitry Andric return Match; 414bdd1243dSDimitry Andric if (const auto *BT = argTy->getAs<BuiltinType>()) { 415bdd1243dSDimitry Andric // Check if the only difference between them is signed vs unsigned 416*0fca6ea1SDimitry Andric // if true, return match signedness. 4170b57cec5SDimitry Andric switch (BT->getKind()) { 4180b57cec5SDimitry Andric default: 4190b57cec5SDimitry Andric break; 4205f757f3fSDimitry Andric case BuiltinType::Bool: 4215f757f3fSDimitry Andric if (Ptr && (T == C.UnsignedCharTy || T == C.SignedCharTy)) 4225f757f3fSDimitry Andric return NoMatch; 4235f757f3fSDimitry Andric [[fallthrough]]; 4240b57cec5SDimitry Andric case BuiltinType::Char_S: 4250b57cec5SDimitry Andric case BuiltinType::SChar: 426*0fca6ea1SDimitry Andric if (T == C.UnsignedShortTy || T == C.ShortTy) 427*0fca6ea1SDimitry Andric return NoMatchTypeConfusion; 428*0fca6ea1SDimitry Andric if (T == C.UnsignedCharTy) 429*0fca6ea1SDimitry Andric return NoMatchSignedness; 430*0fca6ea1SDimitry Andric if (T == C.SignedCharTy) 431*0fca6ea1SDimitry Andric return Match; 432*0fca6ea1SDimitry Andric break; 4330b57cec5SDimitry Andric case BuiltinType::Char_U: 4340b57cec5SDimitry Andric case BuiltinType::UChar: 435a7dea167SDimitry Andric if (T == C.UnsignedShortTy || T == C.ShortTy) 436a7dea167SDimitry Andric return NoMatchTypeConfusion; 437*0fca6ea1SDimitry Andric if (T == C.UnsignedCharTy) 438bdd1243dSDimitry Andric return Match; 439*0fca6ea1SDimitry Andric if (T == C.SignedCharTy) 440*0fca6ea1SDimitry Andric return NoMatchSignedness; 441bdd1243dSDimitry Andric break; 4420b57cec5SDimitry Andric case BuiltinType::Short: 443bdd1243dSDimitry Andric if (T == C.UnsignedShortTy) 444*0fca6ea1SDimitry Andric return NoMatchSignedness; 445bdd1243dSDimitry Andric break; 4460b57cec5SDimitry Andric case BuiltinType::UShort: 447bdd1243dSDimitry Andric if (T == C.ShortTy) 448*0fca6ea1SDimitry Andric return NoMatchSignedness; 449bdd1243dSDimitry Andric break; 4500b57cec5SDimitry Andric case BuiltinType::Int: 451bdd1243dSDimitry Andric if (T == C.UnsignedIntTy) 452*0fca6ea1SDimitry Andric return NoMatchSignedness; 453bdd1243dSDimitry Andric break; 4540b57cec5SDimitry Andric case BuiltinType::UInt: 455bdd1243dSDimitry Andric if (T == C.IntTy) 456*0fca6ea1SDimitry Andric return NoMatchSignedness; 457bdd1243dSDimitry Andric break; 4580b57cec5SDimitry Andric case BuiltinType::Long: 459bdd1243dSDimitry Andric if (T == C.UnsignedLongTy) 460*0fca6ea1SDimitry Andric return NoMatchSignedness; 461bdd1243dSDimitry Andric break; 4620b57cec5SDimitry Andric case BuiltinType::ULong: 463bdd1243dSDimitry Andric if (T == C.LongTy) 464*0fca6ea1SDimitry Andric return NoMatchSignedness; 465bdd1243dSDimitry Andric break; 4660b57cec5SDimitry Andric case BuiltinType::LongLong: 467bdd1243dSDimitry Andric if (T == C.UnsignedLongLongTy) 468*0fca6ea1SDimitry Andric return NoMatchSignedness; 469bdd1243dSDimitry Andric break; 4700b57cec5SDimitry Andric case BuiltinType::ULongLong: 471bdd1243dSDimitry Andric if (T == C.LongLongTy) 472*0fca6ea1SDimitry Andric return NoMatchSignedness; 473bdd1243dSDimitry Andric break; 474bdd1243dSDimitry Andric } 475bdd1243dSDimitry Andric // "Partially matched" because of promotions? 476bdd1243dSDimitry Andric if (!Ptr) { 477bdd1243dSDimitry Andric switch (BT->getKind()) { 478bdd1243dSDimitry Andric default: 479bdd1243dSDimitry Andric break; 4805f757f3fSDimitry Andric case BuiltinType::Bool: 4815f757f3fSDimitry Andric if (T == C.IntTy || T == C.UnsignedIntTy) 4825f757f3fSDimitry Andric return MatchPromotion; 4835f757f3fSDimitry Andric break; 484bdd1243dSDimitry Andric case BuiltinType::Int: 485bdd1243dSDimitry Andric case BuiltinType::UInt: 486bdd1243dSDimitry Andric if (T == C.SignedCharTy || T == C.UnsignedCharTy || 487bdd1243dSDimitry Andric T == C.ShortTy || T == C.UnsignedShortTy || T == C.WCharTy || 488bdd1243dSDimitry Andric T == C.WideCharTy) 489bdd1243dSDimitry Andric return MatchPromotion; 490bdd1243dSDimitry Andric break; 4915f757f3fSDimitry Andric case BuiltinType::Char_U: 4925f757f3fSDimitry Andric if (T == C.UnsignedIntTy) 4935f757f3fSDimitry Andric return MatchPromotion; 4945f757f3fSDimitry Andric if (T == C.UnsignedShortTy) 4955f757f3fSDimitry Andric return NoMatchPromotionTypeConfusion; 4965f757f3fSDimitry Andric break; 4975f757f3fSDimitry Andric case BuiltinType::Char_S: 4985f757f3fSDimitry Andric if (T == C.IntTy) 4995f757f3fSDimitry Andric return MatchPromotion; 5005f757f3fSDimitry Andric if (T == C.ShortTy) 5015f757f3fSDimitry Andric return NoMatchPromotionTypeConfusion; 5025f757f3fSDimitry Andric break; 5035f757f3fSDimitry Andric case BuiltinType::Half: 5045f757f3fSDimitry Andric case BuiltinType::Float: 5055f757f3fSDimitry Andric if (T == C.DoubleTy) 5065f757f3fSDimitry Andric return MatchPromotion; 5075f757f3fSDimitry Andric break; 508bdd1243dSDimitry Andric case BuiltinType::Short: 509bdd1243dSDimitry Andric case BuiltinType::UShort: 510bdd1243dSDimitry Andric if (T == C.SignedCharTy || T == C.UnsignedCharTy) 511bdd1243dSDimitry Andric return NoMatchPromotionTypeConfusion; 512bdd1243dSDimitry Andric break; 513bdd1243dSDimitry Andric case BuiltinType::WChar_U: 514bdd1243dSDimitry Andric case BuiltinType::WChar_S: 515bdd1243dSDimitry Andric if (T != C.WCharTy && T != C.WideCharTy) 516bdd1243dSDimitry Andric return NoMatchPromotionTypeConfusion; 517bdd1243dSDimitry Andric } 518bdd1243dSDimitry Andric } 5190b57cec5SDimitry Andric } 5200b57cec5SDimitry Andric return NoMatch; 5210b57cec5SDimitry Andric } 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric case CStrTy: { 5240b57cec5SDimitry Andric const PointerType *PT = argTy->getAs<PointerType>(); 5250b57cec5SDimitry Andric if (!PT) 5260b57cec5SDimitry Andric return NoMatch; 5270b57cec5SDimitry Andric QualType pointeeTy = PT->getPointeeType(); 5280b57cec5SDimitry Andric if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) 5290b57cec5SDimitry Andric switch (BT->getKind()) { 5300b57cec5SDimitry Andric case BuiltinType::Char_U: 5310b57cec5SDimitry Andric case BuiltinType::UChar: 5320b57cec5SDimitry Andric case BuiltinType::Char_S: 5330b57cec5SDimitry Andric case BuiltinType::SChar: 5340b57cec5SDimitry Andric return Match; 5350b57cec5SDimitry Andric default: 5360b57cec5SDimitry Andric break; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric return NoMatch; 5400b57cec5SDimitry Andric } 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric case WCStrTy: { 5430b57cec5SDimitry Andric const PointerType *PT = argTy->getAs<PointerType>(); 5440b57cec5SDimitry Andric if (!PT) 5450b57cec5SDimitry Andric return NoMatch; 5460b57cec5SDimitry Andric QualType pointeeTy = 5470b57cec5SDimitry Andric C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); 5480b57cec5SDimitry Andric return pointeeTy == C.getWideCharType() ? Match : NoMatch; 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric case WIntTy: { 5520b57cec5SDimitry Andric QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType(); 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt) 5550b57cec5SDimitry Andric return Match; 5560b57cec5SDimitry Andric 557bdd1243dSDimitry Andric QualType PromoArg = C.isPromotableIntegerType(argTy) 5580b57cec5SDimitry Andric ? C.getPromotedIntegerType(argTy) 5590b57cec5SDimitry Andric : argTy; 5600b57cec5SDimitry Andric PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric // If the promoted argument is the corresponding signed type of the 5630b57cec5SDimitry Andric // wint_t type, then it should match. 5640b57cec5SDimitry Andric if (PromoArg->hasSignedIntegerRepresentation() && 5650b57cec5SDimitry Andric C.getCorrespondingUnsignedType(PromoArg) == WInt) 5660b57cec5SDimitry Andric return Match; 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric return WInt == PromoArg ? Match : NoMatch; 5690b57cec5SDimitry Andric } 5700b57cec5SDimitry Andric 5710b57cec5SDimitry Andric case CPointerTy: 5720b57cec5SDimitry Andric if (argTy->isVoidPointerType()) { 5730b57cec5SDimitry Andric return Match; 5740b57cec5SDimitry Andric } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() || 5750b57cec5SDimitry Andric argTy->isBlockPointerType() || argTy->isNullPtrType()) { 5760b57cec5SDimitry Andric return NoMatchPedantic; 5770b57cec5SDimitry Andric } else { 5780b57cec5SDimitry Andric return NoMatch; 5790b57cec5SDimitry Andric } 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric case ObjCPointerTy: { 5820b57cec5SDimitry Andric if (argTy->getAs<ObjCObjectPointerType>() || 5830b57cec5SDimitry Andric argTy->getAs<BlockPointerType>()) 5840b57cec5SDimitry Andric return Match; 5850b57cec5SDimitry Andric 5860b57cec5SDimitry Andric // Handle implicit toll-free bridging. 5870b57cec5SDimitry Andric if (const PointerType *PT = argTy->getAs<PointerType>()) { 5880b57cec5SDimitry Andric // Things such as CFTypeRef are really just opaque pointers 5890b57cec5SDimitry Andric // to C structs representing CF types that can often be bridged 5900b57cec5SDimitry Andric // to Objective-C objects. Since the compiler doesn't know which 5910b57cec5SDimitry Andric // structs can be toll-free bridged, we just accept them all. 5920b57cec5SDimitry Andric QualType pointee = PT->getPointeeType(); 5930b57cec5SDimitry Andric if (pointee->getAsStructureType() || pointee->isVoidType()) 5940b57cec5SDimitry Andric return Match; 5950b57cec5SDimitry Andric } 5960b57cec5SDimitry Andric return NoMatch; 5970b57cec5SDimitry Andric } 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric 6000b57cec5SDimitry Andric llvm_unreachable("Invalid ArgType Kind!"); 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const { 6040b57cec5SDimitry Andric // Check for valid vector element types. 6050b57cec5SDimitry Andric if (T.isNull()) 6060b57cec5SDimitry Andric return ArgType::Invalid(); 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric QualType Vec = C.getExtVectorType(T, NumElts); 6090b57cec5SDimitry Andric return ArgType(Vec, Name); 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric QualType ArgType::getRepresentativeType(ASTContext &C) const { 6130b57cec5SDimitry Andric QualType Res; 6140b57cec5SDimitry Andric switch (K) { 6150b57cec5SDimitry Andric case InvalidTy: 6160b57cec5SDimitry Andric llvm_unreachable("No representative type for Invalid ArgType"); 6170b57cec5SDimitry Andric case UnknownTy: 6180b57cec5SDimitry Andric llvm_unreachable("No representative type for Unknown ArgType"); 6190b57cec5SDimitry Andric case AnyCharTy: 6200b57cec5SDimitry Andric Res = C.CharTy; 6210b57cec5SDimitry Andric break; 6220b57cec5SDimitry Andric case SpecificTy: 6230b57cec5SDimitry Andric Res = T; 6240b57cec5SDimitry Andric break; 6250b57cec5SDimitry Andric case CStrTy: 6260b57cec5SDimitry Andric Res = C.getPointerType(C.CharTy); 6270b57cec5SDimitry Andric break; 6280b57cec5SDimitry Andric case WCStrTy: 6290b57cec5SDimitry Andric Res = C.getPointerType(C.getWideCharType()); 6300b57cec5SDimitry Andric break; 6310b57cec5SDimitry Andric case ObjCPointerTy: 6320b57cec5SDimitry Andric Res = C.ObjCBuiltinIdTy; 6330b57cec5SDimitry Andric break; 6340b57cec5SDimitry Andric case CPointerTy: 6350b57cec5SDimitry Andric Res = C.VoidPtrTy; 6360b57cec5SDimitry Andric break; 6370b57cec5SDimitry Andric case WIntTy: { 6380b57cec5SDimitry Andric Res = C.getWIntType(); 6390b57cec5SDimitry Andric break; 6400b57cec5SDimitry Andric } 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric if (Ptr) 6440b57cec5SDimitry Andric Res = C.getPointerType(Res); 6450b57cec5SDimitry Andric return Res; 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric std::string ArgType::getRepresentativeTypeName(ASTContext &C) const { 6495ffd83dbSDimitry Andric std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy()); 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric std::string Alias; 6520b57cec5SDimitry Andric if (Name) { 6530b57cec5SDimitry Andric // Use a specific name for this type, e.g. "size_t". 6540b57cec5SDimitry Andric Alias = Name; 6550b57cec5SDimitry Andric if (Ptr) { 6560b57cec5SDimitry Andric // If ArgType is actually a pointer to T, append an asterisk. 6570b57cec5SDimitry Andric Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *"; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric // If Alias is the same as the underlying type, e.g. wchar_t, then drop it. 6600b57cec5SDimitry Andric if (S == Alias) 6610b57cec5SDimitry Andric Alias.clear(); 6620b57cec5SDimitry Andric } 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric if (!Alias.empty()) 6650b57cec5SDimitry Andric return std::string("'") + Alias + "' (aka '" + S + "')"; 6660b57cec5SDimitry Andric return std::string("'") + S + "'"; 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6710b57cec5SDimitry Andric // Methods on OptionalAmount. 6720b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric ArgType 6750b57cec5SDimitry Andric analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const { 6760b57cec5SDimitry Andric return Ctx.IntTy; 6770b57cec5SDimitry Andric } 6780b57cec5SDimitry Andric 6790b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6800b57cec5SDimitry Andric // Methods on LengthModifier. 6810b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric const char * 6840b57cec5SDimitry Andric analyze_format_string::LengthModifier::toString() const { 6850b57cec5SDimitry Andric switch (kind) { 6860b57cec5SDimitry Andric case AsChar: 6870b57cec5SDimitry Andric return "hh"; 6880b57cec5SDimitry Andric case AsShort: 6890b57cec5SDimitry Andric return "h"; 6900b57cec5SDimitry Andric case AsShortLong: 6910b57cec5SDimitry Andric return "hl"; 6920b57cec5SDimitry Andric case AsLong: // or AsWideChar 6930b57cec5SDimitry Andric return "l"; 6940b57cec5SDimitry Andric case AsLongLong: 6950b57cec5SDimitry Andric return "ll"; 6960b57cec5SDimitry Andric case AsQuad: 6970b57cec5SDimitry Andric return "q"; 6980b57cec5SDimitry Andric case AsIntMax: 6990b57cec5SDimitry Andric return "j"; 7000b57cec5SDimitry Andric case AsSizeT: 7010b57cec5SDimitry Andric return "z"; 7020b57cec5SDimitry Andric case AsPtrDiff: 7030b57cec5SDimitry Andric return "t"; 7040b57cec5SDimitry Andric case AsInt32: 7050b57cec5SDimitry Andric return "I32"; 7060b57cec5SDimitry Andric case AsInt3264: 7070b57cec5SDimitry Andric return "I"; 7080b57cec5SDimitry Andric case AsInt64: 7090b57cec5SDimitry Andric return "I64"; 7100b57cec5SDimitry Andric case AsLongDouble: 7110b57cec5SDimitry Andric return "L"; 7120b57cec5SDimitry Andric case AsAllocate: 7130b57cec5SDimitry Andric return "a"; 7140b57cec5SDimitry Andric case AsMAllocate: 7150b57cec5SDimitry Andric return "m"; 7160b57cec5SDimitry Andric case AsWide: 7170b57cec5SDimitry Andric return "w"; 7180b57cec5SDimitry Andric case None: 7190b57cec5SDimitry Andric return ""; 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric return nullptr; 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7250b57cec5SDimitry Andric // Methods on ConversionSpecifier. 7260b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric const char *ConversionSpecifier::toString() const { 7290b57cec5SDimitry Andric switch (kind) { 730bdd1243dSDimitry Andric case bArg: return "b"; 731bdd1243dSDimitry Andric case BArg: return "B"; 7320b57cec5SDimitry Andric case dArg: return "d"; 7330b57cec5SDimitry Andric case DArg: return "D"; 7340b57cec5SDimitry Andric case iArg: return "i"; 7350b57cec5SDimitry Andric case oArg: return "o"; 7360b57cec5SDimitry Andric case OArg: return "O"; 7370b57cec5SDimitry Andric case uArg: return "u"; 7380b57cec5SDimitry Andric case UArg: return "U"; 7390b57cec5SDimitry Andric case xArg: return "x"; 7400b57cec5SDimitry Andric case XArg: return "X"; 7410b57cec5SDimitry Andric case fArg: return "f"; 7420b57cec5SDimitry Andric case FArg: return "F"; 7430b57cec5SDimitry Andric case eArg: return "e"; 7440b57cec5SDimitry Andric case EArg: return "E"; 7450b57cec5SDimitry Andric case gArg: return "g"; 7460b57cec5SDimitry Andric case GArg: return "G"; 7470b57cec5SDimitry Andric case aArg: return "a"; 7480b57cec5SDimitry Andric case AArg: return "A"; 7490b57cec5SDimitry Andric case cArg: return "c"; 7500b57cec5SDimitry Andric case sArg: return "s"; 7510b57cec5SDimitry Andric case pArg: return "p"; 7520b57cec5SDimitry Andric case PArg: 7530b57cec5SDimitry Andric return "P"; 7540b57cec5SDimitry Andric case nArg: return "n"; 7550b57cec5SDimitry Andric case PercentArg: return "%"; 7560b57cec5SDimitry Andric case ScanListArg: return "["; 7570b57cec5SDimitry Andric case InvalidSpecifier: return nullptr; 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric // POSIX unicode extensions. 7600b57cec5SDimitry Andric case CArg: return "C"; 7610b57cec5SDimitry Andric case SArg: return "S"; 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric // Objective-C specific specifiers. 7640b57cec5SDimitry Andric case ObjCObjArg: return "@"; 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric // FreeBSD kernel specific specifiers. 7670b57cec5SDimitry Andric case FreeBSDbArg: return "b"; 7680b57cec5SDimitry Andric case FreeBSDDArg: return "D"; 7690b57cec5SDimitry Andric case FreeBSDrArg: return "r"; 7700b57cec5SDimitry Andric case FreeBSDyArg: return "y"; 7710b57cec5SDimitry Andric 7720b57cec5SDimitry Andric // GlibC specific specifiers. 7730b57cec5SDimitry Andric case PrintErrno: return "m"; 7740b57cec5SDimitry Andric 7750b57cec5SDimitry Andric // MS specific specifiers. 7760b57cec5SDimitry Andric case ZArg: return "Z"; 777*0fca6ea1SDimitry Andric 778*0fca6ea1SDimitry Andric // ISO/IEC TR 18037 (fixed-point) specific specifiers. 779*0fca6ea1SDimitry Andric case rArg: 780*0fca6ea1SDimitry Andric return "r"; 781*0fca6ea1SDimitry Andric case RArg: 782*0fca6ea1SDimitry Andric return "R"; 783*0fca6ea1SDimitry Andric case kArg: 784*0fca6ea1SDimitry Andric return "k"; 785*0fca6ea1SDimitry Andric case KArg: 786*0fca6ea1SDimitry Andric return "K"; 7870b57cec5SDimitry Andric } 7880b57cec5SDimitry Andric return nullptr; 7890b57cec5SDimitry Andric } 7900b57cec5SDimitry Andric 791bdd1243dSDimitry Andric std::optional<ConversionSpecifier> 7920b57cec5SDimitry Andric ConversionSpecifier::getStandardSpecifier() const { 7930b57cec5SDimitry Andric ConversionSpecifier::Kind NewKind; 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric switch (getKind()) { 7960b57cec5SDimitry Andric default: 797bdd1243dSDimitry Andric return std::nullopt; 7980b57cec5SDimitry Andric case DArg: 7990b57cec5SDimitry Andric NewKind = dArg; 8000b57cec5SDimitry Andric break; 8010b57cec5SDimitry Andric case UArg: 8020b57cec5SDimitry Andric NewKind = uArg; 8030b57cec5SDimitry Andric break; 8040b57cec5SDimitry Andric case OArg: 8050b57cec5SDimitry Andric NewKind = oArg; 8060b57cec5SDimitry Andric break; 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric ConversionSpecifier FixedCS(*this); 8100b57cec5SDimitry Andric FixedCS.setKind(NewKind); 8110b57cec5SDimitry Andric return FixedCS; 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8150b57cec5SDimitry Andric // Methods on OptionalAmount. 8160b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8170b57cec5SDimitry Andric 8180b57cec5SDimitry Andric void OptionalAmount::toString(raw_ostream &os) const { 8190b57cec5SDimitry Andric switch (hs) { 8200b57cec5SDimitry Andric case Invalid: 8210b57cec5SDimitry Andric case NotSpecified: 8220b57cec5SDimitry Andric return; 8230b57cec5SDimitry Andric case Arg: 8240b57cec5SDimitry Andric if (UsesDotPrefix) 8250b57cec5SDimitry Andric os << "."; 8260b57cec5SDimitry Andric if (usesPositionalArg()) 8270b57cec5SDimitry Andric os << "*" << getPositionalArgIndex() << "$"; 8280b57cec5SDimitry Andric else 8290b57cec5SDimitry Andric os << "*"; 8300b57cec5SDimitry Andric break; 8310b57cec5SDimitry Andric case Constant: 8320b57cec5SDimitry Andric if (UsesDotPrefix) 8330b57cec5SDimitry Andric os << "."; 8340b57cec5SDimitry Andric os << amt; 8350b57cec5SDimitry Andric break; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric } 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, 8400b57cec5SDimitry Andric const LangOptions &LO) const { 8410b57cec5SDimitry Andric switch (LM.getKind()) { 8420b57cec5SDimitry Andric case LengthModifier::None: 8430b57cec5SDimitry Andric return true; 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric // Handle most integer flags 8460b57cec5SDimitry Andric case LengthModifier::AsShort: 8470b57cec5SDimitry Andric // Length modifier only applies to FP vectors. 8480b57cec5SDimitry Andric if (LO.OpenCL && CS.isDoubleArg()) 8490b57cec5SDimitry Andric return !VectorNumElts.isInvalid(); 8500b57cec5SDimitry Andric 851*0fca6ea1SDimitry Andric if (CS.isFixedPointArg()) 852*0fca6ea1SDimitry Andric return true; 853*0fca6ea1SDimitry Andric 8540b57cec5SDimitry Andric if (Target.getTriple().isOSMSVCRT()) { 8550b57cec5SDimitry Andric switch (CS.getKind()) { 8560b57cec5SDimitry Andric case ConversionSpecifier::cArg: 8570b57cec5SDimitry Andric case ConversionSpecifier::CArg: 8580b57cec5SDimitry Andric case ConversionSpecifier::sArg: 8590b57cec5SDimitry Andric case ConversionSpecifier::SArg: 8600b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 8610b57cec5SDimitry Andric return true; 8620b57cec5SDimitry Andric default: 8630b57cec5SDimitry Andric break; 8640b57cec5SDimitry Andric } 8650b57cec5SDimitry Andric } 866bdd1243dSDimitry Andric [[fallthrough]]; 8670b57cec5SDimitry Andric case LengthModifier::AsChar: 8680b57cec5SDimitry Andric case LengthModifier::AsLongLong: 8690b57cec5SDimitry Andric case LengthModifier::AsQuad: 8700b57cec5SDimitry Andric case LengthModifier::AsIntMax: 8710b57cec5SDimitry Andric case LengthModifier::AsSizeT: 8720b57cec5SDimitry Andric case LengthModifier::AsPtrDiff: 8730b57cec5SDimitry Andric switch (CS.getKind()) { 874bdd1243dSDimitry Andric case ConversionSpecifier::bArg: 875bdd1243dSDimitry Andric case ConversionSpecifier::BArg: 8760b57cec5SDimitry Andric case ConversionSpecifier::dArg: 8770b57cec5SDimitry Andric case ConversionSpecifier::DArg: 8780b57cec5SDimitry Andric case ConversionSpecifier::iArg: 8790b57cec5SDimitry Andric case ConversionSpecifier::oArg: 8800b57cec5SDimitry Andric case ConversionSpecifier::OArg: 8810b57cec5SDimitry Andric case ConversionSpecifier::uArg: 8820b57cec5SDimitry Andric case ConversionSpecifier::UArg: 8830b57cec5SDimitry Andric case ConversionSpecifier::xArg: 8840b57cec5SDimitry Andric case ConversionSpecifier::XArg: 8850b57cec5SDimitry Andric case ConversionSpecifier::nArg: 8860b57cec5SDimitry Andric return true; 8870b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDrArg: 8880b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDyArg: 88981ad6265SDimitry Andric return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS(); 8900b57cec5SDimitry Andric default: 8910b57cec5SDimitry Andric return false; 8920b57cec5SDimitry Andric } 8930b57cec5SDimitry Andric 8940b57cec5SDimitry Andric case LengthModifier::AsShortLong: 8950b57cec5SDimitry Andric return LO.OpenCL && !VectorNumElts.isInvalid(); 8960b57cec5SDimitry Andric 8970b57cec5SDimitry Andric // Handle 'l' flag 8980b57cec5SDimitry Andric case LengthModifier::AsLong: // or AsWideChar 8990b57cec5SDimitry Andric if (CS.isDoubleArg()) { 9000b57cec5SDimitry Andric // Invalid for OpenCL FP scalars. 9010b57cec5SDimitry Andric if (LO.OpenCL && VectorNumElts.isInvalid()) 9020b57cec5SDimitry Andric return false; 9030b57cec5SDimitry Andric return true; 9040b57cec5SDimitry Andric } 9050b57cec5SDimitry Andric 906*0fca6ea1SDimitry Andric if (CS.isFixedPointArg()) 907*0fca6ea1SDimitry Andric return true; 908*0fca6ea1SDimitry Andric 9090b57cec5SDimitry Andric switch (CS.getKind()) { 91006c3fb27SDimitry Andric case ConversionSpecifier::bArg: 91106c3fb27SDimitry Andric case ConversionSpecifier::BArg: 9120b57cec5SDimitry Andric case ConversionSpecifier::dArg: 9130b57cec5SDimitry Andric case ConversionSpecifier::DArg: 9140b57cec5SDimitry Andric case ConversionSpecifier::iArg: 9150b57cec5SDimitry Andric case ConversionSpecifier::oArg: 9160b57cec5SDimitry Andric case ConversionSpecifier::OArg: 9170b57cec5SDimitry Andric case ConversionSpecifier::uArg: 9180b57cec5SDimitry Andric case ConversionSpecifier::UArg: 9190b57cec5SDimitry Andric case ConversionSpecifier::xArg: 9200b57cec5SDimitry Andric case ConversionSpecifier::XArg: 9210b57cec5SDimitry Andric case ConversionSpecifier::nArg: 9220b57cec5SDimitry Andric case ConversionSpecifier::cArg: 9230b57cec5SDimitry Andric case ConversionSpecifier::sArg: 9240b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 9250b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 9260b57cec5SDimitry Andric return true; 9270b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDrArg: 9280b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDyArg: 92981ad6265SDimitry Andric return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS(); 9300b57cec5SDimitry Andric default: 9310b57cec5SDimitry Andric return false; 9320b57cec5SDimitry Andric } 9330b57cec5SDimitry Andric 9340b57cec5SDimitry Andric case LengthModifier::AsLongDouble: 9350b57cec5SDimitry Andric switch (CS.getKind()) { 9360b57cec5SDimitry Andric case ConversionSpecifier::aArg: 9370b57cec5SDimitry Andric case ConversionSpecifier::AArg: 9380b57cec5SDimitry Andric case ConversionSpecifier::fArg: 9390b57cec5SDimitry Andric case ConversionSpecifier::FArg: 9400b57cec5SDimitry Andric case ConversionSpecifier::eArg: 9410b57cec5SDimitry Andric case ConversionSpecifier::EArg: 9420b57cec5SDimitry Andric case ConversionSpecifier::gArg: 9430b57cec5SDimitry Andric case ConversionSpecifier::GArg: 9440b57cec5SDimitry Andric return true; 9450b57cec5SDimitry Andric // GNU libc extension. 9460b57cec5SDimitry Andric case ConversionSpecifier::dArg: 9470b57cec5SDimitry Andric case ConversionSpecifier::iArg: 9480b57cec5SDimitry Andric case ConversionSpecifier::oArg: 9490b57cec5SDimitry Andric case ConversionSpecifier::uArg: 9500b57cec5SDimitry Andric case ConversionSpecifier::xArg: 9510b57cec5SDimitry Andric case ConversionSpecifier::XArg: 9520b57cec5SDimitry Andric return !Target.getTriple().isOSDarwin() && 9530b57cec5SDimitry Andric !Target.getTriple().isOSWindows(); 9540b57cec5SDimitry Andric default: 9550b57cec5SDimitry Andric return false; 9560b57cec5SDimitry Andric } 9570b57cec5SDimitry Andric 9580b57cec5SDimitry Andric case LengthModifier::AsAllocate: 9590b57cec5SDimitry Andric switch (CS.getKind()) { 9600b57cec5SDimitry Andric case ConversionSpecifier::sArg: 9610b57cec5SDimitry Andric case ConversionSpecifier::SArg: 9620b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 9630b57cec5SDimitry Andric return true; 9640b57cec5SDimitry Andric default: 9650b57cec5SDimitry Andric return false; 9660b57cec5SDimitry Andric } 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric case LengthModifier::AsMAllocate: 9690b57cec5SDimitry Andric switch (CS.getKind()) { 9700b57cec5SDimitry Andric case ConversionSpecifier::cArg: 9710b57cec5SDimitry Andric case ConversionSpecifier::CArg: 9720b57cec5SDimitry Andric case ConversionSpecifier::sArg: 9730b57cec5SDimitry Andric case ConversionSpecifier::SArg: 9740b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 9750b57cec5SDimitry Andric return true; 9760b57cec5SDimitry Andric default: 9770b57cec5SDimitry Andric return false; 9780b57cec5SDimitry Andric } 9790b57cec5SDimitry Andric case LengthModifier::AsInt32: 9800b57cec5SDimitry Andric case LengthModifier::AsInt3264: 9810b57cec5SDimitry Andric case LengthModifier::AsInt64: 9820b57cec5SDimitry Andric switch (CS.getKind()) { 9830b57cec5SDimitry Andric case ConversionSpecifier::dArg: 9840b57cec5SDimitry Andric case ConversionSpecifier::iArg: 9850b57cec5SDimitry Andric case ConversionSpecifier::oArg: 9860b57cec5SDimitry Andric case ConversionSpecifier::uArg: 9870b57cec5SDimitry Andric case ConversionSpecifier::xArg: 9880b57cec5SDimitry Andric case ConversionSpecifier::XArg: 9890b57cec5SDimitry Andric return Target.getTriple().isOSMSVCRT(); 9900b57cec5SDimitry Andric default: 9910b57cec5SDimitry Andric return false; 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric case LengthModifier::AsWide: 9940b57cec5SDimitry Andric switch (CS.getKind()) { 9950b57cec5SDimitry Andric case ConversionSpecifier::cArg: 9960b57cec5SDimitry Andric case ConversionSpecifier::CArg: 9970b57cec5SDimitry Andric case ConversionSpecifier::sArg: 9980b57cec5SDimitry Andric case ConversionSpecifier::SArg: 9990b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 10000b57cec5SDimitry Andric return Target.getTriple().isOSMSVCRT(); 10010b57cec5SDimitry Andric default: 10020b57cec5SDimitry Andric return false; 10030b57cec5SDimitry Andric } 10040b57cec5SDimitry Andric } 10050b57cec5SDimitry Andric llvm_unreachable("Invalid LengthModifier Kind!"); 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric bool FormatSpecifier::hasStandardLengthModifier() const { 10090b57cec5SDimitry Andric switch (LM.getKind()) { 10100b57cec5SDimitry Andric case LengthModifier::None: 10110b57cec5SDimitry Andric case LengthModifier::AsChar: 10120b57cec5SDimitry Andric case LengthModifier::AsShort: 10130b57cec5SDimitry Andric case LengthModifier::AsLong: 10140b57cec5SDimitry Andric case LengthModifier::AsLongLong: 10150b57cec5SDimitry Andric case LengthModifier::AsIntMax: 10160b57cec5SDimitry Andric case LengthModifier::AsSizeT: 10170b57cec5SDimitry Andric case LengthModifier::AsPtrDiff: 10180b57cec5SDimitry Andric case LengthModifier::AsLongDouble: 10190b57cec5SDimitry Andric return true; 10200b57cec5SDimitry Andric case LengthModifier::AsAllocate: 10210b57cec5SDimitry Andric case LengthModifier::AsMAllocate: 10220b57cec5SDimitry Andric case LengthModifier::AsQuad: 10230b57cec5SDimitry Andric case LengthModifier::AsInt32: 10240b57cec5SDimitry Andric case LengthModifier::AsInt3264: 10250b57cec5SDimitry Andric case LengthModifier::AsInt64: 10260b57cec5SDimitry Andric case LengthModifier::AsWide: 10270b57cec5SDimitry Andric case LengthModifier::AsShortLong: // ??? 10280b57cec5SDimitry Andric return false; 10290b57cec5SDimitry Andric } 10300b57cec5SDimitry Andric llvm_unreachable("Invalid LengthModifier Kind!"); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric bool FormatSpecifier::hasStandardConversionSpecifier( 10340b57cec5SDimitry Andric const LangOptions &LangOpt) const { 10350b57cec5SDimitry Andric switch (CS.getKind()) { 1036bdd1243dSDimitry Andric case ConversionSpecifier::bArg: 1037bdd1243dSDimitry Andric case ConversionSpecifier::BArg: 10380b57cec5SDimitry Andric case ConversionSpecifier::cArg: 10390b57cec5SDimitry Andric case ConversionSpecifier::dArg: 10400b57cec5SDimitry Andric case ConversionSpecifier::iArg: 10410b57cec5SDimitry Andric case ConversionSpecifier::oArg: 10420b57cec5SDimitry Andric case ConversionSpecifier::uArg: 10430b57cec5SDimitry Andric case ConversionSpecifier::xArg: 10440b57cec5SDimitry Andric case ConversionSpecifier::XArg: 10450b57cec5SDimitry Andric case ConversionSpecifier::fArg: 10460b57cec5SDimitry Andric case ConversionSpecifier::FArg: 10470b57cec5SDimitry Andric case ConversionSpecifier::eArg: 10480b57cec5SDimitry Andric case ConversionSpecifier::EArg: 10490b57cec5SDimitry Andric case ConversionSpecifier::gArg: 10500b57cec5SDimitry Andric case ConversionSpecifier::GArg: 10510b57cec5SDimitry Andric case ConversionSpecifier::aArg: 10520b57cec5SDimitry Andric case ConversionSpecifier::AArg: 10530b57cec5SDimitry Andric case ConversionSpecifier::sArg: 10540b57cec5SDimitry Andric case ConversionSpecifier::pArg: 10550b57cec5SDimitry Andric case ConversionSpecifier::nArg: 10560b57cec5SDimitry Andric case ConversionSpecifier::ObjCObjArg: 10570b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 10580b57cec5SDimitry Andric case ConversionSpecifier::PercentArg: 10590b57cec5SDimitry Andric case ConversionSpecifier::PArg: 10600b57cec5SDimitry Andric return true; 10610b57cec5SDimitry Andric case ConversionSpecifier::CArg: 10620b57cec5SDimitry Andric case ConversionSpecifier::SArg: 10630b57cec5SDimitry Andric return LangOpt.ObjC; 10640b57cec5SDimitry Andric case ConversionSpecifier::InvalidSpecifier: 10650b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDbArg: 10660b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDDArg: 10670b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDrArg: 10680b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDyArg: 10690b57cec5SDimitry Andric case ConversionSpecifier::PrintErrno: 10700b57cec5SDimitry Andric case ConversionSpecifier::DArg: 10710b57cec5SDimitry Andric case ConversionSpecifier::OArg: 10720b57cec5SDimitry Andric case ConversionSpecifier::UArg: 10730b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 10740b57cec5SDimitry Andric return false; 1075*0fca6ea1SDimitry Andric case ConversionSpecifier::rArg: 1076*0fca6ea1SDimitry Andric case ConversionSpecifier::RArg: 1077*0fca6ea1SDimitry Andric case ConversionSpecifier::kArg: 1078*0fca6ea1SDimitry Andric case ConversionSpecifier::KArg: 1079*0fca6ea1SDimitry Andric return LangOpt.FixedPoint; 10800b57cec5SDimitry Andric } 10810b57cec5SDimitry Andric llvm_unreachable("Invalid ConversionSpecifier Kind!"); 10820b57cec5SDimitry Andric } 10830b57cec5SDimitry Andric 10840b57cec5SDimitry Andric bool FormatSpecifier::hasStandardLengthConversionCombination() const { 10850b57cec5SDimitry Andric if (LM.getKind() == LengthModifier::AsLongDouble) { 10860b57cec5SDimitry Andric switch(CS.getKind()) { 10870b57cec5SDimitry Andric case ConversionSpecifier::dArg: 10880b57cec5SDimitry Andric case ConversionSpecifier::iArg: 10890b57cec5SDimitry Andric case ConversionSpecifier::oArg: 10900b57cec5SDimitry Andric case ConversionSpecifier::uArg: 10910b57cec5SDimitry Andric case ConversionSpecifier::xArg: 10920b57cec5SDimitry Andric case ConversionSpecifier::XArg: 10930b57cec5SDimitry Andric return false; 10940b57cec5SDimitry Andric default: 10950b57cec5SDimitry Andric return true; 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric return true; 10990b57cec5SDimitry Andric } 11000b57cec5SDimitry Andric 1101bdd1243dSDimitry Andric std::optional<LengthModifier> 1102bdd1243dSDimitry Andric FormatSpecifier::getCorrectedLengthModifier() const { 11030b57cec5SDimitry Andric if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) { 11040b57cec5SDimitry Andric if (LM.getKind() == LengthModifier::AsLongDouble || 11050b57cec5SDimitry Andric LM.getKind() == LengthModifier::AsQuad) { 11060b57cec5SDimitry Andric LengthModifier FixedLM(LM); 11070b57cec5SDimitry Andric FixedLM.setKind(LengthModifier::AsLongLong); 11080b57cec5SDimitry Andric return FixedLM; 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 1112bdd1243dSDimitry Andric return std::nullopt; 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric 11150b57cec5SDimitry Andric bool FormatSpecifier::namedTypeToLengthModifier(QualType QT, 11160b57cec5SDimitry Andric LengthModifier &LM) { 1117bdd1243dSDimitry Andric for (/**/; const auto *TT = QT->getAs<TypedefType>(); 1118bdd1243dSDimitry Andric QT = TT->getDecl()->getUnderlyingType()) { 1119bdd1243dSDimitry Andric const TypedefNameDecl *Typedef = TT->getDecl(); 11200b57cec5SDimitry Andric const IdentifierInfo *Identifier = Typedef->getIdentifier(); 11210b57cec5SDimitry Andric if (Identifier->getName() == "size_t") { 11220b57cec5SDimitry Andric LM.setKind(LengthModifier::AsSizeT); 11230b57cec5SDimitry Andric return true; 11240b57cec5SDimitry Andric } else if (Identifier->getName() == "ssize_t") { 11250b57cec5SDimitry Andric // Not C99, but common in Unix. 11260b57cec5SDimitry Andric LM.setKind(LengthModifier::AsSizeT); 11270b57cec5SDimitry Andric return true; 11280b57cec5SDimitry Andric } else if (Identifier->getName() == "intmax_t") { 11290b57cec5SDimitry Andric LM.setKind(LengthModifier::AsIntMax); 11300b57cec5SDimitry Andric return true; 11310b57cec5SDimitry Andric } else if (Identifier->getName() == "uintmax_t") { 11320b57cec5SDimitry Andric LM.setKind(LengthModifier::AsIntMax); 11330b57cec5SDimitry Andric return true; 11340b57cec5SDimitry Andric } else if (Identifier->getName() == "ptrdiff_t") { 11350b57cec5SDimitry Andric LM.setKind(LengthModifier::AsPtrDiff); 11360b57cec5SDimitry Andric return true; 11370b57cec5SDimitry Andric } 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric return false; 11400b57cec5SDimitry Andric } 1141