1*0b57cec5SDimitry Andric // FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*- 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // Shared details for processing format strings of printf and scanf 10*0b57cec5SDimitry Andric // (and friends). 11*0b57cec5SDimitry Andric // 12*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13*0b57cec5SDimitry Andric 14*0b57cec5SDimitry Andric #include "FormatStringParsing.h" 15*0b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h" 16*0b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 17*0b57cec5SDimitry Andric #include "llvm/Support/ConvertUTF.h" 18*0b57cec5SDimitry Andric 19*0b57cec5SDimitry Andric using clang::analyze_format_string::ArgType; 20*0b57cec5SDimitry Andric using clang::analyze_format_string::FormatStringHandler; 21*0b57cec5SDimitry Andric using clang::analyze_format_string::FormatSpecifier; 22*0b57cec5SDimitry Andric using clang::analyze_format_string::LengthModifier; 23*0b57cec5SDimitry Andric using clang::analyze_format_string::OptionalAmount; 24*0b57cec5SDimitry Andric using clang::analyze_format_string::PositionContext; 25*0b57cec5SDimitry Andric using clang::analyze_format_string::ConversionSpecifier; 26*0b57cec5SDimitry Andric using namespace clang; 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric // Key function to FormatStringHandler. 29*0b57cec5SDimitry Andric FormatStringHandler::~FormatStringHandler() {} 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 32*0b57cec5SDimitry Andric // Functions for parsing format strings components in both printf and 33*0b57cec5SDimitry Andric // scanf format strings. 34*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 35*0b57cec5SDimitry Andric 36*0b57cec5SDimitry Andric OptionalAmount 37*0b57cec5SDimitry Andric clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) { 38*0b57cec5SDimitry Andric const char *I = Beg; 39*0b57cec5SDimitry Andric UpdateOnReturn <const char*> UpdateBeg(Beg, I); 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric unsigned accumulator = 0; 42*0b57cec5SDimitry Andric bool hasDigits = false; 43*0b57cec5SDimitry Andric 44*0b57cec5SDimitry Andric for ( ; I != E; ++I) { 45*0b57cec5SDimitry Andric char c = *I; 46*0b57cec5SDimitry Andric if (c >= '0' && c <= '9') { 47*0b57cec5SDimitry Andric hasDigits = true; 48*0b57cec5SDimitry Andric accumulator = (accumulator * 10) + (c - '0'); 49*0b57cec5SDimitry Andric continue; 50*0b57cec5SDimitry Andric } 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric if (hasDigits) 53*0b57cec5SDimitry Andric return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg, 54*0b57cec5SDimitry Andric false); 55*0b57cec5SDimitry Andric 56*0b57cec5SDimitry Andric break; 57*0b57cec5SDimitry Andric } 58*0b57cec5SDimitry Andric 59*0b57cec5SDimitry Andric return OptionalAmount(); 60*0b57cec5SDimitry Andric } 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric OptionalAmount 63*0b57cec5SDimitry Andric clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg, 64*0b57cec5SDimitry Andric const char *E, 65*0b57cec5SDimitry Andric unsigned &argIndex) { 66*0b57cec5SDimitry Andric if (*Beg == '*') { 67*0b57cec5SDimitry Andric ++Beg; 68*0b57cec5SDimitry Andric return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false); 69*0b57cec5SDimitry Andric } 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric return ParseAmount(Beg, E); 72*0b57cec5SDimitry Andric } 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andric OptionalAmount 75*0b57cec5SDimitry Andric clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H, 76*0b57cec5SDimitry Andric const char *Start, 77*0b57cec5SDimitry Andric const char *&Beg, 78*0b57cec5SDimitry Andric const char *E, 79*0b57cec5SDimitry Andric PositionContext p) { 80*0b57cec5SDimitry Andric if (*Beg == '*') { 81*0b57cec5SDimitry Andric const char *I = Beg + 1; 82*0b57cec5SDimitry Andric const OptionalAmount &Amt = ParseAmount(I, E); 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) { 85*0b57cec5SDimitry Andric H.HandleInvalidPosition(Beg, I - Beg, p); 86*0b57cec5SDimitry Andric return OptionalAmount(false); 87*0b57cec5SDimitry Andric } 88*0b57cec5SDimitry Andric 89*0b57cec5SDimitry Andric if (I == E) { 90*0b57cec5SDimitry Andric // No more characters left? 91*0b57cec5SDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start); 92*0b57cec5SDimitry Andric return OptionalAmount(false); 93*0b57cec5SDimitry Andric } 94*0b57cec5SDimitry Andric 95*0b57cec5SDimitry Andric assert(Amt.getHowSpecified() == OptionalAmount::Constant); 96*0b57cec5SDimitry Andric 97*0b57cec5SDimitry Andric if (*I == '$') { 98*0b57cec5SDimitry Andric // Handle positional arguments 99*0b57cec5SDimitry Andric 100*0b57cec5SDimitry Andric // Special case: '*0$', since this is an easy mistake. 101*0b57cec5SDimitry Andric if (Amt.getConstantAmount() == 0) { 102*0b57cec5SDimitry Andric H.HandleZeroPosition(Beg, I - Beg + 1); 103*0b57cec5SDimitry Andric return OptionalAmount(false); 104*0b57cec5SDimitry Andric } 105*0b57cec5SDimitry Andric 106*0b57cec5SDimitry Andric const char *Tmp = Beg; 107*0b57cec5SDimitry Andric Beg = ++I; 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1, 110*0b57cec5SDimitry Andric Tmp, 0, true); 111*0b57cec5SDimitry Andric } 112*0b57cec5SDimitry Andric 113*0b57cec5SDimitry Andric H.HandleInvalidPosition(Beg, I - Beg, p); 114*0b57cec5SDimitry Andric return OptionalAmount(false); 115*0b57cec5SDimitry Andric } 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric return ParseAmount(Beg, E); 118*0b57cec5SDimitry Andric } 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric 121*0b57cec5SDimitry Andric bool 122*0b57cec5SDimitry Andric clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H, 123*0b57cec5SDimitry Andric FormatSpecifier &CS, 124*0b57cec5SDimitry Andric const char *Start, 125*0b57cec5SDimitry Andric const char *&Beg, const char *E, 126*0b57cec5SDimitry Andric unsigned *argIndex) { 127*0b57cec5SDimitry Andric // FIXME: Support negative field widths. 128*0b57cec5SDimitry Andric if (argIndex) { 129*0b57cec5SDimitry Andric CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex)); 130*0b57cec5SDimitry Andric } 131*0b57cec5SDimitry Andric else { 132*0b57cec5SDimitry Andric const OptionalAmount Amt = 133*0b57cec5SDimitry Andric ParsePositionAmount(H, Start, Beg, E, 134*0b57cec5SDimitry Andric analyze_format_string::FieldWidthPos); 135*0b57cec5SDimitry Andric 136*0b57cec5SDimitry Andric if (Amt.isInvalid()) 137*0b57cec5SDimitry Andric return true; 138*0b57cec5SDimitry Andric CS.setFieldWidth(Amt); 139*0b57cec5SDimitry Andric } 140*0b57cec5SDimitry Andric return false; 141*0b57cec5SDimitry Andric } 142*0b57cec5SDimitry Andric 143*0b57cec5SDimitry Andric bool 144*0b57cec5SDimitry Andric clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H, 145*0b57cec5SDimitry Andric FormatSpecifier &FS, 146*0b57cec5SDimitry Andric const char *Start, 147*0b57cec5SDimitry Andric const char *&Beg, 148*0b57cec5SDimitry Andric const char *E) { 149*0b57cec5SDimitry Andric const char *I = Beg; 150*0b57cec5SDimitry Andric 151*0b57cec5SDimitry Andric const OptionalAmount &Amt = ParseAmount(I, E); 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric if (I == E) { 154*0b57cec5SDimitry Andric // No more characters left? 155*0b57cec5SDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start); 156*0b57cec5SDimitry Andric return true; 157*0b57cec5SDimitry Andric } 158*0b57cec5SDimitry Andric 159*0b57cec5SDimitry Andric if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') { 160*0b57cec5SDimitry Andric // Warn that positional arguments are non-standard. 161*0b57cec5SDimitry Andric H.HandlePosition(Start, I - Start); 162*0b57cec5SDimitry Andric 163*0b57cec5SDimitry Andric // Special case: '%0$', since this is an easy mistake. 164*0b57cec5SDimitry Andric if (Amt.getConstantAmount() == 0) { 165*0b57cec5SDimitry Andric H.HandleZeroPosition(Start, I - Start); 166*0b57cec5SDimitry Andric return true; 167*0b57cec5SDimitry Andric } 168*0b57cec5SDimitry Andric 169*0b57cec5SDimitry Andric FS.setArgIndex(Amt.getConstantAmount() - 1); 170*0b57cec5SDimitry Andric FS.setUsesPositionalArg(); 171*0b57cec5SDimitry Andric // Update the caller's pointer if we decided to consume 172*0b57cec5SDimitry Andric // these characters. 173*0b57cec5SDimitry Andric Beg = I; 174*0b57cec5SDimitry Andric return false; 175*0b57cec5SDimitry Andric } 176*0b57cec5SDimitry Andric 177*0b57cec5SDimitry Andric return false; 178*0b57cec5SDimitry Andric } 179*0b57cec5SDimitry Andric 180*0b57cec5SDimitry Andric bool 181*0b57cec5SDimitry Andric clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H, 182*0b57cec5SDimitry Andric FormatSpecifier &FS, 183*0b57cec5SDimitry Andric const char *&I, 184*0b57cec5SDimitry Andric const char *E, 185*0b57cec5SDimitry Andric const LangOptions &LO) { 186*0b57cec5SDimitry Andric if (!LO.OpenCL) 187*0b57cec5SDimitry Andric return false; 188*0b57cec5SDimitry Andric 189*0b57cec5SDimitry Andric const char *Start = I; 190*0b57cec5SDimitry Andric if (*I == 'v') { 191*0b57cec5SDimitry Andric ++I; 192*0b57cec5SDimitry Andric 193*0b57cec5SDimitry Andric if (I == E) { 194*0b57cec5SDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start); 195*0b57cec5SDimitry Andric return true; 196*0b57cec5SDimitry Andric } 197*0b57cec5SDimitry Andric 198*0b57cec5SDimitry Andric OptionalAmount NumElts = ParseAmount(I, E); 199*0b57cec5SDimitry Andric if (NumElts.getHowSpecified() != OptionalAmount::Constant) { 200*0b57cec5SDimitry Andric H.HandleIncompleteSpecifier(Start, E - Start); 201*0b57cec5SDimitry Andric return true; 202*0b57cec5SDimitry Andric } 203*0b57cec5SDimitry Andric 204*0b57cec5SDimitry Andric FS.setVectorNumElts(NumElts); 205*0b57cec5SDimitry Andric } 206*0b57cec5SDimitry Andric 207*0b57cec5SDimitry Andric return false; 208*0b57cec5SDimitry Andric } 209*0b57cec5SDimitry Andric 210*0b57cec5SDimitry Andric bool 211*0b57cec5SDimitry Andric clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS, 212*0b57cec5SDimitry Andric const char *&I, 213*0b57cec5SDimitry Andric const char *E, 214*0b57cec5SDimitry Andric const LangOptions &LO, 215*0b57cec5SDimitry Andric bool IsScanf) { 216*0b57cec5SDimitry Andric LengthModifier::Kind lmKind = LengthModifier::None; 217*0b57cec5SDimitry Andric const char *lmPosition = I; 218*0b57cec5SDimitry Andric switch (*I) { 219*0b57cec5SDimitry Andric default: 220*0b57cec5SDimitry Andric return false; 221*0b57cec5SDimitry Andric case 'h': 222*0b57cec5SDimitry Andric ++I; 223*0b57cec5SDimitry Andric if (I != E && *I == 'h') { 224*0b57cec5SDimitry Andric ++I; 225*0b57cec5SDimitry Andric lmKind = LengthModifier::AsChar; 226*0b57cec5SDimitry Andric } else if (I != E && *I == 'l' && LO.OpenCL) { 227*0b57cec5SDimitry Andric ++I; 228*0b57cec5SDimitry Andric lmKind = LengthModifier::AsShortLong; 229*0b57cec5SDimitry Andric } else { 230*0b57cec5SDimitry Andric lmKind = LengthModifier::AsShort; 231*0b57cec5SDimitry Andric } 232*0b57cec5SDimitry Andric break; 233*0b57cec5SDimitry Andric case 'l': 234*0b57cec5SDimitry Andric ++I; 235*0b57cec5SDimitry Andric if (I != E && *I == 'l') { 236*0b57cec5SDimitry Andric ++I; 237*0b57cec5SDimitry Andric lmKind = LengthModifier::AsLongLong; 238*0b57cec5SDimitry Andric } else { 239*0b57cec5SDimitry Andric lmKind = LengthModifier::AsLong; 240*0b57cec5SDimitry Andric } 241*0b57cec5SDimitry Andric break; 242*0b57cec5SDimitry Andric case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; 243*0b57cec5SDimitry Andric case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; 244*0b57cec5SDimitry Andric case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; 245*0b57cec5SDimitry Andric case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; 246*0b57cec5SDimitry Andric case 'q': lmKind = LengthModifier::AsQuad; ++I; break; 247*0b57cec5SDimitry Andric case 'a': 248*0b57cec5SDimitry Andric if (IsScanf && !LO.C99 && !LO.CPlusPlus11) { 249*0b57cec5SDimitry Andric // For scanf in C90, look at the next character to see if this should 250*0b57cec5SDimitry Andric // be parsed as the GNU extension 'a' length modifier. If not, this 251*0b57cec5SDimitry Andric // will be parsed as a conversion specifier. 252*0b57cec5SDimitry Andric ++I; 253*0b57cec5SDimitry Andric if (I != E && (*I == 's' || *I == 'S' || *I == '[')) { 254*0b57cec5SDimitry Andric lmKind = LengthModifier::AsAllocate; 255*0b57cec5SDimitry Andric break; 256*0b57cec5SDimitry Andric } 257*0b57cec5SDimitry Andric --I; 258*0b57cec5SDimitry Andric } 259*0b57cec5SDimitry Andric return false; 260*0b57cec5SDimitry Andric case 'm': 261*0b57cec5SDimitry Andric if (IsScanf) { 262*0b57cec5SDimitry Andric lmKind = LengthModifier::AsMAllocate; 263*0b57cec5SDimitry Andric ++I; 264*0b57cec5SDimitry Andric break; 265*0b57cec5SDimitry Andric } 266*0b57cec5SDimitry Andric return false; 267*0b57cec5SDimitry Andric // printf: AsInt64, AsInt32, AsInt3264 268*0b57cec5SDimitry Andric // scanf: AsInt64 269*0b57cec5SDimitry Andric case 'I': 270*0b57cec5SDimitry Andric if (I + 1 != E && I + 2 != E) { 271*0b57cec5SDimitry Andric if (I[1] == '6' && I[2] == '4') { 272*0b57cec5SDimitry Andric I += 3; 273*0b57cec5SDimitry Andric lmKind = LengthModifier::AsInt64; 274*0b57cec5SDimitry Andric break; 275*0b57cec5SDimitry Andric } 276*0b57cec5SDimitry Andric if (IsScanf) 277*0b57cec5SDimitry Andric return false; 278*0b57cec5SDimitry Andric 279*0b57cec5SDimitry Andric if (I[1] == '3' && I[2] == '2') { 280*0b57cec5SDimitry Andric I += 3; 281*0b57cec5SDimitry Andric lmKind = LengthModifier::AsInt32; 282*0b57cec5SDimitry Andric break; 283*0b57cec5SDimitry Andric } 284*0b57cec5SDimitry Andric } 285*0b57cec5SDimitry Andric ++I; 286*0b57cec5SDimitry Andric lmKind = LengthModifier::AsInt3264; 287*0b57cec5SDimitry Andric break; 288*0b57cec5SDimitry Andric case 'w': 289*0b57cec5SDimitry Andric lmKind = LengthModifier::AsWide; ++I; break; 290*0b57cec5SDimitry Andric } 291*0b57cec5SDimitry Andric LengthModifier lm(lmPosition, lmKind); 292*0b57cec5SDimitry Andric FS.setLengthModifier(lm); 293*0b57cec5SDimitry Andric return true; 294*0b57cec5SDimitry Andric } 295*0b57cec5SDimitry Andric 296*0b57cec5SDimitry Andric bool clang::analyze_format_string::ParseUTF8InvalidSpecifier( 297*0b57cec5SDimitry Andric const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) { 298*0b57cec5SDimitry Andric if (SpecifierBegin + 1 >= FmtStrEnd) 299*0b57cec5SDimitry Andric return false; 300*0b57cec5SDimitry Andric 301*0b57cec5SDimitry Andric const llvm::UTF8 *SB = 302*0b57cec5SDimitry Andric reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1); 303*0b57cec5SDimitry Andric const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd); 304*0b57cec5SDimitry Andric const char FirstByte = *SB; 305*0b57cec5SDimitry Andric 306*0b57cec5SDimitry Andric // If the invalid specifier is a multibyte UTF-8 string, return the 307*0b57cec5SDimitry Andric // total length accordingly so that the conversion specifier can be 308*0b57cec5SDimitry Andric // properly updated to reflect a complete UTF-8 specifier. 309*0b57cec5SDimitry Andric unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte); 310*0b57cec5SDimitry Andric if (NumBytes == 1) 311*0b57cec5SDimitry Andric return false; 312*0b57cec5SDimitry Andric if (SB + NumBytes > SE) 313*0b57cec5SDimitry Andric return false; 314*0b57cec5SDimitry Andric 315*0b57cec5SDimitry Andric Len = NumBytes + 1; 316*0b57cec5SDimitry Andric return true; 317*0b57cec5SDimitry Andric } 318*0b57cec5SDimitry Andric 319*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 320*0b57cec5SDimitry Andric // Methods on ArgType. 321*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 322*0b57cec5SDimitry Andric 323*0b57cec5SDimitry Andric clang::analyze_format_string::ArgType::MatchKind 324*0b57cec5SDimitry Andric ArgType::matchesType(ASTContext &C, QualType argTy) const { 325*0b57cec5SDimitry Andric if (Ptr) { 326*0b57cec5SDimitry Andric // It has to be a pointer. 327*0b57cec5SDimitry Andric const PointerType *PT = argTy->getAs<PointerType>(); 328*0b57cec5SDimitry Andric if (!PT) 329*0b57cec5SDimitry Andric return NoMatch; 330*0b57cec5SDimitry Andric 331*0b57cec5SDimitry Andric // We cannot write through a const qualified pointer. 332*0b57cec5SDimitry Andric if (PT->getPointeeType().isConstQualified()) 333*0b57cec5SDimitry Andric return NoMatch; 334*0b57cec5SDimitry Andric 335*0b57cec5SDimitry Andric argTy = PT->getPointeeType(); 336*0b57cec5SDimitry Andric } 337*0b57cec5SDimitry Andric 338*0b57cec5SDimitry Andric switch (K) { 339*0b57cec5SDimitry Andric case InvalidTy: 340*0b57cec5SDimitry Andric llvm_unreachable("ArgType must be valid"); 341*0b57cec5SDimitry Andric 342*0b57cec5SDimitry Andric case UnknownTy: 343*0b57cec5SDimitry Andric return Match; 344*0b57cec5SDimitry Andric 345*0b57cec5SDimitry Andric case AnyCharTy: { 346*0b57cec5SDimitry Andric if (const EnumType *ETy = argTy->getAs<EnumType>()) { 347*0b57cec5SDimitry Andric // If the enum is incomplete we know nothing about the underlying type. 348*0b57cec5SDimitry Andric // Assume that it's 'int'. 349*0b57cec5SDimitry Andric if (!ETy->getDecl()->isComplete()) 350*0b57cec5SDimitry Andric return NoMatch; 351*0b57cec5SDimitry Andric argTy = ETy->getDecl()->getIntegerType(); 352*0b57cec5SDimitry Andric } 353*0b57cec5SDimitry Andric 354*0b57cec5SDimitry Andric if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) 355*0b57cec5SDimitry Andric switch (BT->getKind()) { 356*0b57cec5SDimitry Andric default: 357*0b57cec5SDimitry Andric break; 358*0b57cec5SDimitry Andric case BuiltinType::Char_S: 359*0b57cec5SDimitry Andric case BuiltinType::SChar: 360*0b57cec5SDimitry Andric case BuiltinType::UChar: 361*0b57cec5SDimitry Andric case BuiltinType::Char_U: 362*0b57cec5SDimitry Andric return Match; 363*0b57cec5SDimitry Andric } 364*0b57cec5SDimitry Andric return NoMatch; 365*0b57cec5SDimitry Andric } 366*0b57cec5SDimitry Andric 367*0b57cec5SDimitry Andric case SpecificTy: { 368*0b57cec5SDimitry Andric if (const EnumType *ETy = argTy->getAs<EnumType>()) { 369*0b57cec5SDimitry Andric // If the enum is incomplete we know nothing about the underlying type. 370*0b57cec5SDimitry Andric // Assume that it's 'int'. 371*0b57cec5SDimitry Andric if (!ETy->getDecl()->isComplete()) 372*0b57cec5SDimitry Andric argTy = C.IntTy; 373*0b57cec5SDimitry Andric else 374*0b57cec5SDimitry Andric argTy = ETy->getDecl()->getIntegerType(); 375*0b57cec5SDimitry Andric } 376*0b57cec5SDimitry Andric argTy = C.getCanonicalType(argTy).getUnqualifiedType(); 377*0b57cec5SDimitry Andric 378*0b57cec5SDimitry Andric if (T == argTy) 379*0b57cec5SDimitry Andric return Match; 380*0b57cec5SDimitry Andric // Check for "compatible types". 381*0b57cec5SDimitry Andric if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) 382*0b57cec5SDimitry Andric switch (BT->getKind()) { 383*0b57cec5SDimitry Andric default: 384*0b57cec5SDimitry Andric break; 385*0b57cec5SDimitry Andric case BuiltinType::Char_S: 386*0b57cec5SDimitry Andric case BuiltinType::SChar: 387*0b57cec5SDimitry Andric case BuiltinType::Char_U: 388*0b57cec5SDimitry Andric case BuiltinType::UChar: 389*0b57cec5SDimitry Andric return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match 390*0b57cec5SDimitry Andric : NoMatch; 391*0b57cec5SDimitry Andric case BuiltinType::Short: 392*0b57cec5SDimitry Andric return T == C.UnsignedShortTy ? Match : NoMatch; 393*0b57cec5SDimitry Andric case BuiltinType::UShort: 394*0b57cec5SDimitry Andric return T == C.ShortTy ? Match : NoMatch; 395*0b57cec5SDimitry Andric case BuiltinType::Int: 396*0b57cec5SDimitry Andric return T == C.UnsignedIntTy ? Match : NoMatch; 397*0b57cec5SDimitry Andric case BuiltinType::UInt: 398*0b57cec5SDimitry Andric return T == C.IntTy ? Match : NoMatch; 399*0b57cec5SDimitry Andric case BuiltinType::Long: 400*0b57cec5SDimitry Andric return T == C.UnsignedLongTy ? Match : NoMatch; 401*0b57cec5SDimitry Andric case BuiltinType::ULong: 402*0b57cec5SDimitry Andric return T == C.LongTy ? Match : NoMatch; 403*0b57cec5SDimitry Andric case BuiltinType::LongLong: 404*0b57cec5SDimitry Andric return T == C.UnsignedLongLongTy ? Match : NoMatch; 405*0b57cec5SDimitry Andric case BuiltinType::ULongLong: 406*0b57cec5SDimitry Andric return T == C.LongLongTy ? Match : NoMatch; 407*0b57cec5SDimitry Andric } 408*0b57cec5SDimitry Andric return NoMatch; 409*0b57cec5SDimitry Andric } 410*0b57cec5SDimitry Andric 411*0b57cec5SDimitry Andric case CStrTy: { 412*0b57cec5SDimitry Andric const PointerType *PT = argTy->getAs<PointerType>(); 413*0b57cec5SDimitry Andric if (!PT) 414*0b57cec5SDimitry Andric return NoMatch; 415*0b57cec5SDimitry Andric QualType pointeeTy = PT->getPointeeType(); 416*0b57cec5SDimitry Andric if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) 417*0b57cec5SDimitry Andric switch (BT->getKind()) { 418*0b57cec5SDimitry Andric case BuiltinType::Void: 419*0b57cec5SDimitry Andric case BuiltinType::Char_U: 420*0b57cec5SDimitry Andric case BuiltinType::UChar: 421*0b57cec5SDimitry Andric case BuiltinType::Char_S: 422*0b57cec5SDimitry Andric case BuiltinType::SChar: 423*0b57cec5SDimitry Andric return Match; 424*0b57cec5SDimitry Andric default: 425*0b57cec5SDimitry Andric break; 426*0b57cec5SDimitry Andric } 427*0b57cec5SDimitry Andric 428*0b57cec5SDimitry Andric return NoMatch; 429*0b57cec5SDimitry Andric } 430*0b57cec5SDimitry Andric 431*0b57cec5SDimitry Andric case WCStrTy: { 432*0b57cec5SDimitry Andric const PointerType *PT = argTy->getAs<PointerType>(); 433*0b57cec5SDimitry Andric if (!PT) 434*0b57cec5SDimitry Andric return NoMatch; 435*0b57cec5SDimitry Andric QualType pointeeTy = 436*0b57cec5SDimitry Andric C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); 437*0b57cec5SDimitry Andric return pointeeTy == C.getWideCharType() ? Match : NoMatch; 438*0b57cec5SDimitry Andric } 439*0b57cec5SDimitry Andric 440*0b57cec5SDimitry Andric case WIntTy: { 441*0b57cec5SDimitry Andric QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType(); 442*0b57cec5SDimitry Andric 443*0b57cec5SDimitry Andric if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt) 444*0b57cec5SDimitry Andric return Match; 445*0b57cec5SDimitry Andric 446*0b57cec5SDimitry Andric QualType PromoArg = argTy->isPromotableIntegerType() 447*0b57cec5SDimitry Andric ? C.getPromotedIntegerType(argTy) 448*0b57cec5SDimitry Andric : argTy; 449*0b57cec5SDimitry Andric PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType(); 450*0b57cec5SDimitry Andric 451*0b57cec5SDimitry Andric // If the promoted argument is the corresponding signed type of the 452*0b57cec5SDimitry Andric // wint_t type, then it should match. 453*0b57cec5SDimitry Andric if (PromoArg->hasSignedIntegerRepresentation() && 454*0b57cec5SDimitry Andric C.getCorrespondingUnsignedType(PromoArg) == WInt) 455*0b57cec5SDimitry Andric return Match; 456*0b57cec5SDimitry Andric 457*0b57cec5SDimitry Andric return WInt == PromoArg ? Match : NoMatch; 458*0b57cec5SDimitry Andric } 459*0b57cec5SDimitry Andric 460*0b57cec5SDimitry Andric case CPointerTy: 461*0b57cec5SDimitry Andric if (argTy->isVoidPointerType()) { 462*0b57cec5SDimitry Andric return Match; 463*0b57cec5SDimitry Andric } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() || 464*0b57cec5SDimitry Andric argTy->isBlockPointerType() || argTy->isNullPtrType()) { 465*0b57cec5SDimitry Andric return NoMatchPedantic; 466*0b57cec5SDimitry Andric } else { 467*0b57cec5SDimitry Andric return NoMatch; 468*0b57cec5SDimitry Andric } 469*0b57cec5SDimitry Andric 470*0b57cec5SDimitry Andric case ObjCPointerTy: { 471*0b57cec5SDimitry Andric if (argTy->getAs<ObjCObjectPointerType>() || 472*0b57cec5SDimitry Andric argTy->getAs<BlockPointerType>()) 473*0b57cec5SDimitry Andric return Match; 474*0b57cec5SDimitry Andric 475*0b57cec5SDimitry Andric // Handle implicit toll-free bridging. 476*0b57cec5SDimitry Andric if (const PointerType *PT = argTy->getAs<PointerType>()) { 477*0b57cec5SDimitry Andric // Things such as CFTypeRef are really just opaque pointers 478*0b57cec5SDimitry Andric // to C structs representing CF types that can often be bridged 479*0b57cec5SDimitry Andric // to Objective-C objects. Since the compiler doesn't know which 480*0b57cec5SDimitry Andric // structs can be toll-free bridged, we just accept them all. 481*0b57cec5SDimitry Andric QualType pointee = PT->getPointeeType(); 482*0b57cec5SDimitry Andric if (pointee->getAsStructureType() || pointee->isVoidType()) 483*0b57cec5SDimitry Andric return Match; 484*0b57cec5SDimitry Andric } 485*0b57cec5SDimitry Andric return NoMatch; 486*0b57cec5SDimitry Andric } 487*0b57cec5SDimitry Andric } 488*0b57cec5SDimitry Andric 489*0b57cec5SDimitry Andric llvm_unreachable("Invalid ArgType Kind!"); 490*0b57cec5SDimitry Andric } 491*0b57cec5SDimitry Andric 492*0b57cec5SDimitry Andric ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const { 493*0b57cec5SDimitry Andric // Check for valid vector element types. 494*0b57cec5SDimitry Andric if (T.isNull()) 495*0b57cec5SDimitry Andric return ArgType::Invalid(); 496*0b57cec5SDimitry Andric 497*0b57cec5SDimitry Andric QualType Vec = C.getExtVectorType(T, NumElts); 498*0b57cec5SDimitry Andric return ArgType(Vec, Name); 499*0b57cec5SDimitry Andric } 500*0b57cec5SDimitry Andric 501*0b57cec5SDimitry Andric QualType ArgType::getRepresentativeType(ASTContext &C) const { 502*0b57cec5SDimitry Andric QualType Res; 503*0b57cec5SDimitry Andric switch (K) { 504*0b57cec5SDimitry Andric case InvalidTy: 505*0b57cec5SDimitry Andric llvm_unreachable("No representative type for Invalid ArgType"); 506*0b57cec5SDimitry Andric case UnknownTy: 507*0b57cec5SDimitry Andric llvm_unreachable("No representative type for Unknown ArgType"); 508*0b57cec5SDimitry Andric case AnyCharTy: 509*0b57cec5SDimitry Andric Res = C.CharTy; 510*0b57cec5SDimitry Andric break; 511*0b57cec5SDimitry Andric case SpecificTy: 512*0b57cec5SDimitry Andric Res = T; 513*0b57cec5SDimitry Andric break; 514*0b57cec5SDimitry Andric case CStrTy: 515*0b57cec5SDimitry Andric Res = C.getPointerType(C.CharTy); 516*0b57cec5SDimitry Andric break; 517*0b57cec5SDimitry Andric case WCStrTy: 518*0b57cec5SDimitry Andric Res = C.getPointerType(C.getWideCharType()); 519*0b57cec5SDimitry Andric break; 520*0b57cec5SDimitry Andric case ObjCPointerTy: 521*0b57cec5SDimitry Andric Res = C.ObjCBuiltinIdTy; 522*0b57cec5SDimitry Andric break; 523*0b57cec5SDimitry Andric case CPointerTy: 524*0b57cec5SDimitry Andric Res = C.VoidPtrTy; 525*0b57cec5SDimitry Andric break; 526*0b57cec5SDimitry Andric case WIntTy: { 527*0b57cec5SDimitry Andric Res = C.getWIntType(); 528*0b57cec5SDimitry Andric break; 529*0b57cec5SDimitry Andric } 530*0b57cec5SDimitry Andric } 531*0b57cec5SDimitry Andric 532*0b57cec5SDimitry Andric if (Ptr) 533*0b57cec5SDimitry Andric Res = C.getPointerType(Res); 534*0b57cec5SDimitry Andric return Res; 535*0b57cec5SDimitry Andric } 536*0b57cec5SDimitry Andric 537*0b57cec5SDimitry Andric std::string ArgType::getRepresentativeTypeName(ASTContext &C) const { 538*0b57cec5SDimitry Andric std::string S = getRepresentativeType(C).getAsString(); 539*0b57cec5SDimitry Andric 540*0b57cec5SDimitry Andric std::string Alias; 541*0b57cec5SDimitry Andric if (Name) { 542*0b57cec5SDimitry Andric // Use a specific name for this type, e.g. "size_t". 543*0b57cec5SDimitry Andric Alias = Name; 544*0b57cec5SDimitry Andric if (Ptr) { 545*0b57cec5SDimitry Andric // If ArgType is actually a pointer to T, append an asterisk. 546*0b57cec5SDimitry Andric Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *"; 547*0b57cec5SDimitry Andric } 548*0b57cec5SDimitry Andric // If Alias is the same as the underlying type, e.g. wchar_t, then drop it. 549*0b57cec5SDimitry Andric if (S == Alias) 550*0b57cec5SDimitry Andric Alias.clear(); 551*0b57cec5SDimitry Andric } 552*0b57cec5SDimitry Andric 553*0b57cec5SDimitry Andric if (!Alias.empty()) 554*0b57cec5SDimitry Andric return std::string("'") + Alias + "' (aka '" + S + "')"; 555*0b57cec5SDimitry Andric return std::string("'") + S + "'"; 556*0b57cec5SDimitry Andric } 557*0b57cec5SDimitry Andric 558*0b57cec5SDimitry Andric 559*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 560*0b57cec5SDimitry Andric // Methods on OptionalAmount. 561*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 562*0b57cec5SDimitry Andric 563*0b57cec5SDimitry Andric ArgType 564*0b57cec5SDimitry Andric analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const { 565*0b57cec5SDimitry Andric return Ctx.IntTy; 566*0b57cec5SDimitry Andric } 567*0b57cec5SDimitry Andric 568*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 569*0b57cec5SDimitry Andric // Methods on LengthModifier. 570*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 571*0b57cec5SDimitry Andric 572*0b57cec5SDimitry Andric const char * 573*0b57cec5SDimitry Andric analyze_format_string::LengthModifier::toString() const { 574*0b57cec5SDimitry Andric switch (kind) { 575*0b57cec5SDimitry Andric case AsChar: 576*0b57cec5SDimitry Andric return "hh"; 577*0b57cec5SDimitry Andric case AsShort: 578*0b57cec5SDimitry Andric return "h"; 579*0b57cec5SDimitry Andric case AsShortLong: 580*0b57cec5SDimitry Andric return "hl"; 581*0b57cec5SDimitry Andric case AsLong: // or AsWideChar 582*0b57cec5SDimitry Andric return "l"; 583*0b57cec5SDimitry Andric case AsLongLong: 584*0b57cec5SDimitry Andric return "ll"; 585*0b57cec5SDimitry Andric case AsQuad: 586*0b57cec5SDimitry Andric return "q"; 587*0b57cec5SDimitry Andric case AsIntMax: 588*0b57cec5SDimitry Andric return "j"; 589*0b57cec5SDimitry Andric case AsSizeT: 590*0b57cec5SDimitry Andric return "z"; 591*0b57cec5SDimitry Andric case AsPtrDiff: 592*0b57cec5SDimitry Andric return "t"; 593*0b57cec5SDimitry Andric case AsInt32: 594*0b57cec5SDimitry Andric return "I32"; 595*0b57cec5SDimitry Andric case AsInt3264: 596*0b57cec5SDimitry Andric return "I"; 597*0b57cec5SDimitry Andric case AsInt64: 598*0b57cec5SDimitry Andric return "I64"; 599*0b57cec5SDimitry Andric case AsLongDouble: 600*0b57cec5SDimitry Andric return "L"; 601*0b57cec5SDimitry Andric case AsAllocate: 602*0b57cec5SDimitry Andric return "a"; 603*0b57cec5SDimitry Andric case AsMAllocate: 604*0b57cec5SDimitry Andric return "m"; 605*0b57cec5SDimitry Andric case AsWide: 606*0b57cec5SDimitry Andric return "w"; 607*0b57cec5SDimitry Andric case None: 608*0b57cec5SDimitry Andric return ""; 609*0b57cec5SDimitry Andric } 610*0b57cec5SDimitry Andric return nullptr; 611*0b57cec5SDimitry Andric } 612*0b57cec5SDimitry Andric 613*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 614*0b57cec5SDimitry Andric // Methods on ConversionSpecifier. 615*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 616*0b57cec5SDimitry Andric 617*0b57cec5SDimitry Andric const char *ConversionSpecifier::toString() const { 618*0b57cec5SDimitry Andric switch (kind) { 619*0b57cec5SDimitry Andric case dArg: return "d"; 620*0b57cec5SDimitry Andric case DArg: return "D"; 621*0b57cec5SDimitry Andric case iArg: return "i"; 622*0b57cec5SDimitry Andric case oArg: return "o"; 623*0b57cec5SDimitry Andric case OArg: return "O"; 624*0b57cec5SDimitry Andric case uArg: return "u"; 625*0b57cec5SDimitry Andric case UArg: return "U"; 626*0b57cec5SDimitry Andric case xArg: return "x"; 627*0b57cec5SDimitry Andric case XArg: return "X"; 628*0b57cec5SDimitry Andric case fArg: return "f"; 629*0b57cec5SDimitry Andric case FArg: return "F"; 630*0b57cec5SDimitry Andric case eArg: return "e"; 631*0b57cec5SDimitry Andric case EArg: return "E"; 632*0b57cec5SDimitry Andric case gArg: return "g"; 633*0b57cec5SDimitry Andric case GArg: return "G"; 634*0b57cec5SDimitry Andric case aArg: return "a"; 635*0b57cec5SDimitry Andric case AArg: return "A"; 636*0b57cec5SDimitry Andric case cArg: return "c"; 637*0b57cec5SDimitry Andric case sArg: return "s"; 638*0b57cec5SDimitry Andric case pArg: return "p"; 639*0b57cec5SDimitry Andric case PArg: 640*0b57cec5SDimitry Andric return "P"; 641*0b57cec5SDimitry Andric case nArg: return "n"; 642*0b57cec5SDimitry Andric case PercentArg: return "%"; 643*0b57cec5SDimitry Andric case ScanListArg: return "["; 644*0b57cec5SDimitry Andric case InvalidSpecifier: return nullptr; 645*0b57cec5SDimitry Andric 646*0b57cec5SDimitry Andric // POSIX unicode extensions. 647*0b57cec5SDimitry Andric case CArg: return "C"; 648*0b57cec5SDimitry Andric case SArg: return "S"; 649*0b57cec5SDimitry Andric 650*0b57cec5SDimitry Andric // Objective-C specific specifiers. 651*0b57cec5SDimitry Andric case ObjCObjArg: return "@"; 652*0b57cec5SDimitry Andric 653*0b57cec5SDimitry Andric // FreeBSD kernel specific specifiers. 654*0b57cec5SDimitry Andric case FreeBSDbArg: return "b"; 655*0b57cec5SDimitry Andric case FreeBSDDArg: return "D"; 656*0b57cec5SDimitry Andric case FreeBSDrArg: return "r"; 657*0b57cec5SDimitry Andric case FreeBSDyArg: return "y"; 658*0b57cec5SDimitry Andric 659*0b57cec5SDimitry Andric // GlibC specific specifiers. 660*0b57cec5SDimitry Andric case PrintErrno: return "m"; 661*0b57cec5SDimitry Andric 662*0b57cec5SDimitry Andric // MS specific specifiers. 663*0b57cec5SDimitry Andric case ZArg: return "Z"; 664*0b57cec5SDimitry Andric } 665*0b57cec5SDimitry Andric return nullptr; 666*0b57cec5SDimitry Andric } 667*0b57cec5SDimitry Andric 668*0b57cec5SDimitry Andric Optional<ConversionSpecifier> 669*0b57cec5SDimitry Andric ConversionSpecifier::getStandardSpecifier() const { 670*0b57cec5SDimitry Andric ConversionSpecifier::Kind NewKind; 671*0b57cec5SDimitry Andric 672*0b57cec5SDimitry Andric switch (getKind()) { 673*0b57cec5SDimitry Andric default: 674*0b57cec5SDimitry Andric return None; 675*0b57cec5SDimitry Andric case DArg: 676*0b57cec5SDimitry Andric NewKind = dArg; 677*0b57cec5SDimitry Andric break; 678*0b57cec5SDimitry Andric case UArg: 679*0b57cec5SDimitry Andric NewKind = uArg; 680*0b57cec5SDimitry Andric break; 681*0b57cec5SDimitry Andric case OArg: 682*0b57cec5SDimitry Andric NewKind = oArg; 683*0b57cec5SDimitry Andric break; 684*0b57cec5SDimitry Andric } 685*0b57cec5SDimitry Andric 686*0b57cec5SDimitry Andric ConversionSpecifier FixedCS(*this); 687*0b57cec5SDimitry Andric FixedCS.setKind(NewKind); 688*0b57cec5SDimitry Andric return FixedCS; 689*0b57cec5SDimitry Andric } 690*0b57cec5SDimitry Andric 691*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 692*0b57cec5SDimitry Andric // Methods on OptionalAmount. 693*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 694*0b57cec5SDimitry Andric 695*0b57cec5SDimitry Andric void OptionalAmount::toString(raw_ostream &os) const { 696*0b57cec5SDimitry Andric switch (hs) { 697*0b57cec5SDimitry Andric case Invalid: 698*0b57cec5SDimitry Andric case NotSpecified: 699*0b57cec5SDimitry Andric return; 700*0b57cec5SDimitry Andric case Arg: 701*0b57cec5SDimitry Andric if (UsesDotPrefix) 702*0b57cec5SDimitry Andric os << "."; 703*0b57cec5SDimitry Andric if (usesPositionalArg()) 704*0b57cec5SDimitry Andric os << "*" << getPositionalArgIndex() << "$"; 705*0b57cec5SDimitry Andric else 706*0b57cec5SDimitry Andric os << "*"; 707*0b57cec5SDimitry Andric break; 708*0b57cec5SDimitry Andric case Constant: 709*0b57cec5SDimitry Andric if (UsesDotPrefix) 710*0b57cec5SDimitry Andric os << "."; 711*0b57cec5SDimitry Andric os << amt; 712*0b57cec5SDimitry Andric break; 713*0b57cec5SDimitry Andric } 714*0b57cec5SDimitry Andric } 715*0b57cec5SDimitry Andric 716*0b57cec5SDimitry Andric bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target, 717*0b57cec5SDimitry Andric const LangOptions &LO) const { 718*0b57cec5SDimitry Andric switch (LM.getKind()) { 719*0b57cec5SDimitry Andric case LengthModifier::None: 720*0b57cec5SDimitry Andric return true; 721*0b57cec5SDimitry Andric 722*0b57cec5SDimitry Andric // Handle most integer flags 723*0b57cec5SDimitry Andric case LengthModifier::AsShort: 724*0b57cec5SDimitry Andric // Length modifier only applies to FP vectors. 725*0b57cec5SDimitry Andric if (LO.OpenCL && CS.isDoubleArg()) 726*0b57cec5SDimitry Andric return !VectorNumElts.isInvalid(); 727*0b57cec5SDimitry Andric 728*0b57cec5SDimitry Andric if (Target.getTriple().isOSMSVCRT()) { 729*0b57cec5SDimitry Andric switch (CS.getKind()) { 730*0b57cec5SDimitry Andric case ConversionSpecifier::cArg: 731*0b57cec5SDimitry Andric case ConversionSpecifier::CArg: 732*0b57cec5SDimitry Andric case ConversionSpecifier::sArg: 733*0b57cec5SDimitry Andric case ConversionSpecifier::SArg: 734*0b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 735*0b57cec5SDimitry Andric return true; 736*0b57cec5SDimitry Andric default: 737*0b57cec5SDimitry Andric break; 738*0b57cec5SDimitry Andric } 739*0b57cec5SDimitry Andric } 740*0b57cec5SDimitry Andric LLVM_FALLTHROUGH; 741*0b57cec5SDimitry Andric case LengthModifier::AsChar: 742*0b57cec5SDimitry Andric case LengthModifier::AsLongLong: 743*0b57cec5SDimitry Andric case LengthModifier::AsQuad: 744*0b57cec5SDimitry Andric case LengthModifier::AsIntMax: 745*0b57cec5SDimitry Andric case LengthModifier::AsSizeT: 746*0b57cec5SDimitry Andric case LengthModifier::AsPtrDiff: 747*0b57cec5SDimitry Andric switch (CS.getKind()) { 748*0b57cec5SDimitry Andric case ConversionSpecifier::dArg: 749*0b57cec5SDimitry Andric case ConversionSpecifier::DArg: 750*0b57cec5SDimitry Andric case ConversionSpecifier::iArg: 751*0b57cec5SDimitry Andric case ConversionSpecifier::oArg: 752*0b57cec5SDimitry Andric case ConversionSpecifier::OArg: 753*0b57cec5SDimitry Andric case ConversionSpecifier::uArg: 754*0b57cec5SDimitry Andric case ConversionSpecifier::UArg: 755*0b57cec5SDimitry Andric case ConversionSpecifier::xArg: 756*0b57cec5SDimitry Andric case ConversionSpecifier::XArg: 757*0b57cec5SDimitry Andric case ConversionSpecifier::nArg: 758*0b57cec5SDimitry Andric return true; 759*0b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDrArg: 760*0b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDyArg: 761*0b57cec5SDimitry Andric return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); 762*0b57cec5SDimitry Andric default: 763*0b57cec5SDimitry Andric return false; 764*0b57cec5SDimitry Andric } 765*0b57cec5SDimitry Andric 766*0b57cec5SDimitry Andric case LengthModifier::AsShortLong: 767*0b57cec5SDimitry Andric return LO.OpenCL && !VectorNumElts.isInvalid(); 768*0b57cec5SDimitry Andric 769*0b57cec5SDimitry Andric // Handle 'l' flag 770*0b57cec5SDimitry Andric case LengthModifier::AsLong: // or AsWideChar 771*0b57cec5SDimitry Andric if (CS.isDoubleArg()) { 772*0b57cec5SDimitry Andric // Invalid for OpenCL FP scalars. 773*0b57cec5SDimitry Andric if (LO.OpenCL && VectorNumElts.isInvalid()) 774*0b57cec5SDimitry Andric return false; 775*0b57cec5SDimitry Andric return true; 776*0b57cec5SDimitry Andric } 777*0b57cec5SDimitry Andric 778*0b57cec5SDimitry Andric switch (CS.getKind()) { 779*0b57cec5SDimitry Andric case ConversionSpecifier::dArg: 780*0b57cec5SDimitry Andric case ConversionSpecifier::DArg: 781*0b57cec5SDimitry Andric case ConversionSpecifier::iArg: 782*0b57cec5SDimitry Andric case ConversionSpecifier::oArg: 783*0b57cec5SDimitry Andric case ConversionSpecifier::OArg: 784*0b57cec5SDimitry Andric case ConversionSpecifier::uArg: 785*0b57cec5SDimitry Andric case ConversionSpecifier::UArg: 786*0b57cec5SDimitry Andric case ConversionSpecifier::xArg: 787*0b57cec5SDimitry Andric case ConversionSpecifier::XArg: 788*0b57cec5SDimitry Andric case ConversionSpecifier::nArg: 789*0b57cec5SDimitry Andric case ConversionSpecifier::cArg: 790*0b57cec5SDimitry Andric case ConversionSpecifier::sArg: 791*0b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 792*0b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 793*0b57cec5SDimitry Andric return true; 794*0b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDrArg: 795*0b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDyArg: 796*0b57cec5SDimitry Andric return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4(); 797*0b57cec5SDimitry Andric default: 798*0b57cec5SDimitry Andric return false; 799*0b57cec5SDimitry Andric } 800*0b57cec5SDimitry Andric 801*0b57cec5SDimitry Andric case LengthModifier::AsLongDouble: 802*0b57cec5SDimitry Andric switch (CS.getKind()) { 803*0b57cec5SDimitry Andric case ConversionSpecifier::aArg: 804*0b57cec5SDimitry Andric case ConversionSpecifier::AArg: 805*0b57cec5SDimitry Andric case ConversionSpecifier::fArg: 806*0b57cec5SDimitry Andric case ConversionSpecifier::FArg: 807*0b57cec5SDimitry Andric case ConversionSpecifier::eArg: 808*0b57cec5SDimitry Andric case ConversionSpecifier::EArg: 809*0b57cec5SDimitry Andric case ConversionSpecifier::gArg: 810*0b57cec5SDimitry Andric case ConversionSpecifier::GArg: 811*0b57cec5SDimitry Andric return true; 812*0b57cec5SDimitry Andric // GNU libc extension. 813*0b57cec5SDimitry Andric case ConversionSpecifier::dArg: 814*0b57cec5SDimitry Andric case ConversionSpecifier::iArg: 815*0b57cec5SDimitry Andric case ConversionSpecifier::oArg: 816*0b57cec5SDimitry Andric case ConversionSpecifier::uArg: 817*0b57cec5SDimitry Andric case ConversionSpecifier::xArg: 818*0b57cec5SDimitry Andric case ConversionSpecifier::XArg: 819*0b57cec5SDimitry Andric return !Target.getTriple().isOSDarwin() && 820*0b57cec5SDimitry Andric !Target.getTriple().isOSWindows(); 821*0b57cec5SDimitry Andric default: 822*0b57cec5SDimitry Andric return false; 823*0b57cec5SDimitry Andric } 824*0b57cec5SDimitry Andric 825*0b57cec5SDimitry Andric case LengthModifier::AsAllocate: 826*0b57cec5SDimitry Andric switch (CS.getKind()) { 827*0b57cec5SDimitry Andric case ConversionSpecifier::sArg: 828*0b57cec5SDimitry Andric case ConversionSpecifier::SArg: 829*0b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 830*0b57cec5SDimitry Andric return true; 831*0b57cec5SDimitry Andric default: 832*0b57cec5SDimitry Andric return false; 833*0b57cec5SDimitry Andric } 834*0b57cec5SDimitry Andric 835*0b57cec5SDimitry Andric case LengthModifier::AsMAllocate: 836*0b57cec5SDimitry Andric switch (CS.getKind()) { 837*0b57cec5SDimitry Andric case ConversionSpecifier::cArg: 838*0b57cec5SDimitry Andric case ConversionSpecifier::CArg: 839*0b57cec5SDimitry Andric case ConversionSpecifier::sArg: 840*0b57cec5SDimitry Andric case ConversionSpecifier::SArg: 841*0b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 842*0b57cec5SDimitry Andric return true; 843*0b57cec5SDimitry Andric default: 844*0b57cec5SDimitry Andric return false; 845*0b57cec5SDimitry Andric } 846*0b57cec5SDimitry Andric case LengthModifier::AsInt32: 847*0b57cec5SDimitry Andric case LengthModifier::AsInt3264: 848*0b57cec5SDimitry Andric case LengthModifier::AsInt64: 849*0b57cec5SDimitry Andric switch (CS.getKind()) { 850*0b57cec5SDimitry Andric case ConversionSpecifier::dArg: 851*0b57cec5SDimitry Andric case ConversionSpecifier::iArg: 852*0b57cec5SDimitry Andric case ConversionSpecifier::oArg: 853*0b57cec5SDimitry Andric case ConversionSpecifier::uArg: 854*0b57cec5SDimitry Andric case ConversionSpecifier::xArg: 855*0b57cec5SDimitry Andric case ConversionSpecifier::XArg: 856*0b57cec5SDimitry Andric return Target.getTriple().isOSMSVCRT(); 857*0b57cec5SDimitry Andric default: 858*0b57cec5SDimitry Andric return false; 859*0b57cec5SDimitry Andric } 860*0b57cec5SDimitry Andric case LengthModifier::AsWide: 861*0b57cec5SDimitry Andric switch (CS.getKind()) { 862*0b57cec5SDimitry Andric case ConversionSpecifier::cArg: 863*0b57cec5SDimitry Andric case ConversionSpecifier::CArg: 864*0b57cec5SDimitry Andric case ConversionSpecifier::sArg: 865*0b57cec5SDimitry Andric case ConversionSpecifier::SArg: 866*0b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 867*0b57cec5SDimitry Andric return Target.getTriple().isOSMSVCRT(); 868*0b57cec5SDimitry Andric default: 869*0b57cec5SDimitry Andric return false; 870*0b57cec5SDimitry Andric } 871*0b57cec5SDimitry Andric } 872*0b57cec5SDimitry Andric llvm_unreachable("Invalid LengthModifier Kind!"); 873*0b57cec5SDimitry Andric } 874*0b57cec5SDimitry Andric 875*0b57cec5SDimitry Andric bool FormatSpecifier::hasStandardLengthModifier() const { 876*0b57cec5SDimitry Andric switch (LM.getKind()) { 877*0b57cec5SDimitry Andric case LengthModifier::None: 878*0b57cec5SDimitry Andric case LengthModifier::AsChar: 879*0b57cec5SDimitry Andric case LengthModifier::AsShort: 880*0b57cec5SDimitry Andric case LengthModifier::AsLong: 881*0b57cec5SDimitry Andric case LengthModifier::AsLongLong: 882*0b57cec5SDimitry Andric case LengthModifier::AsIntMax: 883*0b57cec5SDimitry Andric case LengthModifier::AsSizeT: 884*0b57cec5SDimitry Andric case LengthModifier::AsPtrDiff: 885*0b57cec5SDimitry Andric case LengthModifier::AsLongDouble: 886*0b57cec5SDimitry Andric return true; 887*0b57cec5SDimitry Andric case LengthModifier::AsAllocate: 888*0b57cec5SDimitry Andric case LengthModifier::AsMAllocate: 889*0b57cec5SDimitry Andric case LengthModifier::AsQuad: 890*0b57cec5SDimitry Andric case LengthModifier::AsInt32: 891*0b57cec5SDimitry Andric case LengthModifier::AsInt3264: 892*0b57cec5SDimitry Andric case LengthModifier::AsInt64: 893*0b57cec5SDimitry Andric case LengthModifier::AsWide: 894*0b57cec5SDimitry Andric case LengthModifier::AsShortLong: // ??? 895*0b57cec5SDimitry Andric return false; 896*0b57cec5SDimitry Andric } 897*0b57cec5SDimitry Andric llvm_unreachable("Invalid LengthModifier Kind!"); 898*0b57cec5SDimitry Andric } 899*0b57cec5SDimitry Andric 900*0b57cec5SDimitry Andric bool FormatSpecifier::hasStandardConversionSpecifier( 901*0b57cec5SDimitry Andric const LangOptions &LangOpt) const { 902*0b57cec5SDimitry Andric switch (CS.getKind()) { 903*0b57cec5SDimitry Andric case ConversionSpecifier::cArg: 904*0b57cec5SDimitry Andric case ConversionSpecifier::dArg: 905*0b57cec5SDimitry Andric case ConversionSpecifier::iArg: 906*0b57cec5SDimitry Andric case ConversionSpecifier::oArg: 907*0b57cec5SDimitry Andric case ConversionSpecifier::uArg: 908*0b57cec5SDimitry Andric case ConversionSpecifier::xArg: 909*0b57cec5SDimitry Andric case ConversionSpecifier::XArg: 910*0b57cec5SDimitry Andric case ConversionSpecifier::fArg: 911*0b57cec5SDimitry Andric case ConversionSpecifier::FArg: 912*0b57cec5SDimitry Andric case ConversionSpecifier::eArg: 913*0b57cec5SDimitry Andric case ConversionSpecifier::EArg: 914*0b57cec5SDimitry Andric case ConversionSpecifier::gArg: 915*0b57cec5SDimitry Andric case ConversionSpecifier::GArg: 916*0b57cec5SDimitry Andric case ConversionSpecifier::aArg: 917*0b57cec5SDimitry Andric case ConversionSpecifier::AArg: 918*0b57cec5SDimitry Andric case ConversionSpecifier::sArg: 919*0b57cec5SDimitry Andric case ConversionSpecifier::pArg: 920*0b57cec5SDimitry Andric case ConversionSpecifier::nArg: 921*0b57cec5SDimitry Andric case ConversionSpecifier::ObjCObjArg: 922*0b57cec5SDimitry Andric case ConversionSpecifier::ScanListArg: 923*0b57cec5SDimitry Andric case ConversionSpecifier::PercentArg: 924*0b57cec5SDimitry Andric case ConversionSpecifier::PArg: 925*0b57cec5SDimitry Andric return true; 926*0b57cec5SDimitry Andric case ConversionSpecifier::CArg: 927*0b57cec5SDimitry Andric case ConversionSpecifier::SArg: 928*0b57cec5SDimitry Andric return LangOpt.ObjC; 929*0b57cec5SDimitry Andric case ConversionSpecifier::InvalidSpecifier: 930*0b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDbArg: 931*0b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDDArg: 932*0b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDrArg: 933*0b57cec5SDimitry Andric case ConversionSpecifier::FreeBSDyArg: 934*0b57cec5SDimitry Andric case ConversionSpecifier::PrintErrno: 935*0b57cec5SDimitry Andric case ConversionSpecifier::DArg: 936*0b57cec5SDimitry Andric case ConversionSpecifier::OArg: 937*0b57cec5SDimitry Andric case ConversionSpecifier::UArg: 938*0b57cec5SDimitry Andric case ConversionSpecifier::ZArg: 939*0b57cec5SDimitry Andric return false; 940*0b57cec5SDimitry Andric } 941*0b57cec5SDimitry Andric llvm_unreachable("Invalid ConversionSpecifier Kind!"); 942*0b57cec5SDimitry Andric } 943*0b57cec5SDimitry Andric 944*0b57cec5SDimitry Andric bool FormatSpecifier::hasStandardLengthConversionCombination() const { 945*0b57cec5SDimitry Andric if (LM.getKind() == LengthModifier::AsLongDouble) { 946*0b57cec5SDimitry Andric switch(CS.getKind()) { 947*0b57cec5SDimitry Andric case ConversionSpecifier::dArg: 948*0b57cec5SDimitry Andric case ConversionSpecifier::iArg: 949*0b57cec5SDimitry Andric case ConversionSpecifier::oArg: 950*0b57cec5SDimitry Andric case ConversionSpecifier::uArg: 951*0b57cec5SDimitry Andric case ConversionSpecifier::xArg: 952*0b57cec5SDimitry Andric case ConversionSpecifier::XArg: 953*0b57cec5SDimitry Andric return false; 954*0b57cec5SDimitry Andric default: 955*0b57cec5SDimitry Andric return true; 956*0b57cec5SDimitry Andric } 957*0b57cec5SDimitry Andric } 958*0b57cec5SDimitry Andric return true; 959*0b57cec5SDimitry Andric } 960*0b57cec5SDimitry Andric 961*0b57cec5SDimitry Andric Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const { 962*0b57cec5SDimitry Andric if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) { 963*0b57cec5SDimitry Andric if (LM.getKind() == LengthModifier::AsLongDouble || 964*0b57cec5SDimitry Andric LM.getKind() == LengthModifier::AsQuad) { 965*0b57cec5SDimitry Andric LengthModifier FixedLM(LM); 966*0b57cec5SDimitry Andric FixedLM.setKind(LengthModifier::AsLongLong); 967*0b57cec5SDimitry Andric return FixedLM; 968*0b57cec5SDimitry Andric } 969*0b57cec5SDimitry Andric } 970*0b57cec5SDimitry Andric 971*0b57cec5SDimitry Andric return None; 972*0b57cec5SDimitry Andric } 973*0b57cec5SDimitry Andric 974*0b57cec5SDimitry Andric bool FormatSpecifier::namedTypeToLengthModifier(QualType QT, 975*0b57cec5SDimitry Andric LengthModifier &LM) { 976*0b57cec5SDimitry Andric assert(isa<TypedefType>(QT) && "Expected a TypedefType"); 977*0b57cec5SDimitry Andric const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl(); 978*0b57cec5SDimitry Andric 979*0b57cec5SDimitry Andric for (;;) { 980*0b57cec5SDimitry Andric const IdentifierInfo *Identifier = Typedef->getIdentifier(); 981*0b57cec5SDimitry Andric if (Identifier->getName() == "size_t") { 982*0b57cec5SDimitry Andric LM.setKind(LengthModifier::AsSizeT); 983*0b57cec5SDimitry Andric return true; 984*0b57cec5SDimitry Andric } else if (Identifier->getName() == "ssize_t") { 985*0b57cec5SDimitry Andric // Not C99, but common in Unix. 986*0b57cec5SDimitry Andric LM.setKind(LengthModifier::AsSizeT); 987*0b57cec5SDimitry Andric return true; 988*0b57cec5SDimitry Andric } else if (Identifier->getName() == "intmax_t") { 989*0b57cec5SDimitry Andric LM.setKind(LengthModifier::AsIntMax); 990*0b57cec5SDimitry Andric return true; 991*0b57cec5SDimitry Andric } else if (Identifier->getName() == "uintmax_t") { 992*0b57cec5SDimitry Andric LM.setKind(LengthModifier::AsIntMax); 993*0b57cec5SDimitry Andric return true; 994*0b57cec5SDimitry Andric } else if (Identifier->getName() == "ptrdiff_t") { 995*0b57cec5SDimitry Andric LM.setKind(LengthModifier::AsPtrDiff); 996*0b57cec5SDimitry Andric return true; 997*0b57cec5SDimitry Andric } 998*0b57cec5SDimitry Andric 999*0b57cec5SDimitry Andric QualType T = Typedef->getUnderlyingType(); 1000*0b57cec5SDimitry Andric if (!isa<TypedefType>(T)) 1001*0b57cec5SDimitry Andric break; 1002*0b57cec5SDimitry Andric 1003*0b57cec5SDimitry Andric Typedef = cast<TypedefType>(T)->getDecl(); 1004*0b57cec5SDimitry Andric } 1005*0b57cec5SDimitry Andric return false; 1006*0b57cec5SDimitry Andric } 1007