ScanfFormatString.cpp revision 276479
1212795Sdim//= ScanfFormatString.cpp - Analysis of printf format strings --*- C++ -*-===// 2212795Sdim// 3212795Sdim// The LLVM Compiler Infrastructure 4212795Sdim// 5212795Sdim// This file is distributed under the University of Illinois Open Source 6212795Sdim// License. See LICENSE.TXT for details. 7212795Sdim// 8212795Sdim//===----------------------------------------------------------------------===// 9212795Sdim// 10212795Sdim// Handling of format string in scanf and friends. The structure of format 11212795Sdim// strings for fscanf() are described in C99 7.19.6.2. 12212795Sdim// 13212795Sdim//===----------------------------------------------------------------------===// 14212795Sdim 15212795Sdim#include "clang/Analysis/Analyses/FormatString.h" 16249423Sdim#include "FormatStringParsing.h" 17243830Sdim#include "clang/Basic/TargetInfo.h" 18212795Sdim 19239462Sdimusing clang::analyze_format_string::ArgType; 20212795Sdimusing clang::analyze_format_string::FormatStringHandler; 21212795Sdimusing clang::analyze_format_string::LengthModifier; 22212795Sdimusing clang::analyze_format_string::OptionalAmount; 23212795Sdimusing clang::analyze_format_string::ConversionSpecifier; 24212795Sdimusing clang::analyze_scanf::ScanfConversionSpecifier; 25212795Sdimusing clang::analyze_scanf::ScanfSpecifier; 26212795Sdimusing clang::UpdateOnReturn; 27234353Sdimusing namespace clang; 28212795Sdim 29212795Sdimtypedef clang::analyze_format_string::SpecifierResult<ScanfSpecifier> 30212795Sdim ScanfSpecifierResult; 31212795Sdim 32212795Sdimstatic bool ParseScanList(FormatStringHandler &H, 33212795Sdim ScanfConversionSpecifier &CS, 34212795Sdim const char *&Beg, const char *E) { 35212795Sdim const char *I = Beg; 36212795Sdim const char *start = I - 1; 37212795Sdim UpdateOnReturn <const char*> UpdateBeg(Beg, I); 38212795Sdim 39212795Sdim // No more characters? 40212795Sdim if (I == E) { 41212795Sdim H.HandleIncompleteScanList(start, I); 42212795Sdim return true; 43212795Sdim } 44212795Sdim 45212795Sdim // Special case: ']' is the first character. 46212795Sdim if (*I == ']') { 47212795Sdim if (++I == E) { 48212795Sdim H.HandleIncompleteScanList(start, I - 1); 49212795Sdim return true; 50212795Sdim } 51212795Sdim } 52212795Sdim 53276479Sdim // Special case: "^]" are the first characters. 54276479Sdim if (I + 1 != E && I[0] == '^' && I[1] == ']') { 55276479Sdim I += 2; 56276479Sdim if (I == E) { 57276479Sdim H.HandleIncompleteScanList(start, I - 1); 58276479Sdim return true; 59276479Sdim } 60276479Sdim } 61276479Sdim 62212795Sdim // Look for a ']' character which denotes the end of the scan list. 63212795Sdim while (*I != ']') { 64212795Sdim if (++I == E) { 65212795Sdim H.HandleIncompleteScanList(start, I - 1); 66212795Sdim return true; 67212795Sdim } 68212795Sdim } 69212795Sdim 70212795Sdim CS.setEndScanList(I); 71212795Sdim return false; 72212795Sdim} 73212795Sdim 74212795Sdim// FIXME: Much of this is copy-paste from ParsePrintfSpecifier. 75212795Sdim// We can possibly refactor. 76212795Sdimstatic ScanfSpecifierResult ParseScanfSpecifier(FormatStringHandler &H, 77212795Sdim const char *&Beg, 78212795Sdim const char *E, 79234353Sdim unsigned &argIndex, 80243830Sdim const LangOptions &LO, 81243830Sdim const TargetInfo &Target) { 82212795Sdim 83212795Sdim using namespace clang::analyze_scanf; 84212795Sdim const char *I = Beg; 85276479Sdim const char *Start = nullptr; 86212795Sdim UpdateOnReturn <const char*> UpdateBeg(Beg, I); 87212795Sdim 88212795Sdim // Look for a '%' character that indicates the start of a format specifier. 89212795Sdim for ( ; I != E ; ++I) { 90212795Sdim char c = *I; 91212795Sdim if (c == '\0') { 92212795Sdim // Detect spurious null characters, which are likely errors. 93212795Sdim H.HandleNullChar(I); 94212795Sdim return true; 95212795Sdim } 96212795Sdim if (c == '%') { 97212795Sdim Start = I++; // Record the start of the format specifier. 98212795Sdim break; 99212795Sdim } 100212795Sdim } 101212795Sdim 102212795Sdim // No format specifier found? 103212795Sdim if (!Start) 104212795Sdim return false; 105212795Sdim 106212795Sdim if (I == E) { 107212795Sdim // No more characters left? 108212795Sdim H.HandleIncompleteSpecifier(Start, E - Start); 109212795Sdim return true; 110212795Sdim } 111212795Sdim 112212795Sdim ScanfSpecifier FS; 113212795Sdim if (ParseArgPosition(H, FS, Start, I, E)) 114212795Sdim return true; 115212795Sdim 116212795Sdim if (I == E) { 117212795Sdim // No more characters left? 118212795Sdim H.HandleIncompleteSpecifier(Start, E - Start); 119212795Sdim return true; 120212795Sdim } 121212795Sdim 122212795Sdim // Look for '*' flag if it is present. 123212795Sdim if (*I == '*') { 124212795Sdim FS.setSuppressAssignment(I); 125212795Sdim if (++I == E) { 126212795Sdim H.HandleIncompleteSpecifier(Start, E - Start); 127212795Sdim return true; 128212795Sdim } 129212795Sdim } 130212795Sdim 131212795Sdim // Look for the field width (if any). Unlike printf, this is either 132212795Sdim // a fixed integer or isn't present. 133212795Sdim const OptionalAmount &Amt = clang::analyze_format_string::ParseAmount(I, E); 134212795Sdim if (Amt.getHowSpecified() != OptionalAmount::NotSpecified) { 135212795Sdim assert(Amt.getHowSpecified() == OptionalAmount::Constant); 136212795Sdim FS.setFieldWidth(Amt); 137212795Sdim 138212795Sdim if (I == E) { 139212795Sdim // No more characters left? 140212795Sdim H.HandleIncompleteSpecifier(Start, E - Start); 141212795Sdim return true; 142212795Sdim } 143212795Sdim } 144212795Sdim 145212795Sdim // Look for the length modifier. 146234353Sdim if (ParseLengthModifier(FS, I, E, LO, /*scanf=*/true) && I == E) { 147212795Sdim // No more characters left? 148212795Sdim H.HandleIncompleteSpecifier(Start, E - Start); 149212795Sdim return true; 150212795Sdim } 151212795Sdim 152212795Sdim // Detect spurious null characters, which are likely errors. 153212795Sdim if (*I == '\0') { 154212795Sdim H.HandleNullChar(I); 155212795Sdim return true; 156212795Sdim } 157212795Sdim 158212795Sdim // Finally, look for the conversion specifier. 159212795Sdim const char *conversionPosition = I++; 160212795Sdim ScanfConversionSpecifier::Kind k = ScanfConversionSpecifier::InvalidSpecifier; 161212795Sdim switch (*conversionPosition) { 162212795Sdim default: 163212795Sdim break; 164212795Sdim case '%': k = ConversionSpecifier::PercentArg; break; 165212795Sdim case 'A': k = ConversionSpecifier::AArg; break; 166212795Sdim case 'E': k = ConversionSpecifier::EArg; break; 167212795Sdim case 'F': k = ConversionSpecifier::FArg; break; 168212795Sdim case 'G': k = ConversionSpecifier::GArg; break; 169212795Sdim case 'X': k = ConversionSpecifier::XArg; break; 170212795Sdim case 'a': k = ConversionSpecifier::aArg; break; 171212795Sdim case 'd': k = ConversionSpecifier::dArg; break; 172212795Sdim case 'e': k = ConversionSpecifier::eArg; break; 173212795Sdim case 'f': k = ConversionSpecifier::fArg; break; 174212795Sdim case 'g': k = ConversionSpecifier::gArg; break; 175212795Sdim case 'i': k = ConversionSpecifier::iArg; break; 176212795Sdim case 'n': k = ConversionSpecifier::nArg; break; 177212795Sdim case 'c': k = ConversionSpecifier::cArg; break; 178212795Sdim case 'C': k = ConversionSpecifier::CArg; break; 179212795Sdim case 'S': k = ConversionSpecifier::SArg; break; 180212795Sdim case '[': k = ConversionSpecifier::ScanListArg; break; 181212795Sdim case 'u': k = ConversionSpecifier::uArg; break; 182212795Sdim case 'x': k = ConversionSpecifier::xArg; break; 183212795Sdim case 'o': k = ConversionSpecifier::oArg; break; 184212795Sdim case 's': k = ConversionSpecifier::sArg; break; 185212795Sdim case 'p': k = ConversionSpecifier::pArg; break; 186243830Sdim // Apple extensions 187243830Sdim // Apple-specific 188243830Sdim case 'D': 189243830Sdim if (Target.getTriple().isOSDarwin()) 190243830Sdim k = ConversionSpecifier::DArg; 191243830Sdim break; 192243830Sdim case 'O': 193243830Sdim if (Target.getTriple().isOSDarwin()) 194243830Sdim k = ConversionSpecifier::OArg; 195243830Sdim break; 196243830Sdim case 'U': 197243830Sdim if (Target.getTriple().isOSDarwin()) 198243830Sdim k = ConversionSpecifier::UArg; 199243830Sdim break; 200212795Sdim } 201212795Sdim ScanfConversionSpecifier CS(conversionPosition, k); 202212795Sdim if (k == ScanfConversionSpecifier::ScanListArg) { 203234353Sdim if (ParseScanList(H, CS, I, E)) 204212795Sdim return true; 205212795Sdim } 206212795Sdim FS.setConversionSpecifier(CS); 207212795Sdim if (CS.consumesDataArgument() && !FS.getSuppressAssignment() 208212795Sdim && !FS.usesPositionalArg()) 209212795Sdim FS.setArgIndex(argIndex++); 210212795Sdim 211212795Sdim // FIXME: '%' and '*' doesn't make sense. Issue a warning. 212212795Sdim // FIXME: 'ConsumedSoFar' and '*' doesn't make sense. 213212795Sdim 214212795Sdim if (k == ScanfConversionSpecifier::InvalidSpecifier) { 215212795Sdim // Assume the conversion takes one argument. 216212795Sdim return !H.HandleInvalidScanfConversionSpecifier(FS, Beg, I - Beg); 217212795Sdim } 218212795Sdim return ScanfSpecifierResult(Start, FS); 219212795Sdim} 220234353Sdim 221239462SdimArgType ScanfSpecifier::getArgType(ASTContext &Ctx) const { 222234353Sdim const ScanfConversionSpecifier &CS = getConversionSpecifier(); 223234353Sdim 224234353Sdim if (!CS.consumesDataArgument()) 225239462Sdim return ArgType::Invalid(); 226234353Sdim 227234353Sdim switch(CS.getKind()) { 228234353Sdim // Signed int. 229234353Sdim case ConversionSpecifier::dArg: 230243830Sdim case ConversionSpecifier::DArg: 231234353Sdim case ConversionSpecifier::iArg: 232234353Sdim switch (LM.getKind()) { 233239462Sdim case LengthModifier::None: 234239462Sdim return ArgType::PtrTo(Ctx.IntTy); 235234353Sdim case LengthModifier::AsChar: 236239462Sdim return ArgType::PtrTo(ArgType::AnyCharTy); 237239462Sdim case LengthModifier::AsShort: 238239462Sdim return ArgType::PtrTo(Ctx.ShortTy); 239239462Sdim case LengthModifier::AsLong: 240239462Sdim return ArgType::PtrTo(Ctx.LongTy); 241234353Sdim case LengthModifier::AsLongLong: 242234353Sdim case LengthModifier::AsQuad: 243239462Sdim return ArgType::PtrTo(Ctx.LongLongTy); 244261991Sdim case LengthModifier::AsInt64: 245261991Sdim return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64")); 246234353Sdim case LengthModifier::AsIntMax: 247239462Sdim return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); 248234353Sdim case LengthModifier::AsSizeT: 249234353Sdim // FIXME: ssize_t. 250239462Sdim return ArgType(); 251234353Sdim case LengthModifier::AsPtrDiff: 252239462Sdim return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); 253234353Sdim case LengthModifier::AsLongDouble: 254234353Sdim // GNU extension. 255239462Sdim return ArgType::PtrTo(Ctx.LongLongTy); 256239462Sdim case LengthModifier::AsAllocate: 257239462Sdim case LengthModifier::AsMAllocate: 258261991Sdim case LengthModifier::AsInt32: 259261991Sdim case LengthModifier::AsInt3264: 260239462Sdim return ArgType::Invalid(); 261234353Sdim } 262234353Sdim 263234353Sdim // Unsigned int. 264234353Sdim case ConversionSpecifier::oArg: 265243830Sdim case ConversionSpecifier::OArg: 266234353Sdim case ConversionSpecifier::uArg: 267243830Sdim case ConversionSpecifier::UArg: 268234353Sdim case ConversionSpecifier::xArg: 269234353Sdim case ConversionSpecifier::XArg: 270234353Sdim switch (LM.getKind()) { 271239462Sdim case LengthModifier::None: 272239462Sdim return ArgType::PtrTo(Ctx.UnsignedIntTy); 273239462Sdim case LengthModifier::AsChar: 274239462Sdim return ArgType::PtrTo(Ctx.UnsignedCharTy); 275239462Sdim case LengthModifier::AsShort: 276239462Sdim return ArgType::PtrTo(Ctx.UnsignedShortTy); 277239462Sdim case LengthModifier::AsLong: 278239462Sdim return ArgType::PtrTo(Ctx.UnsignedLongTy); 279234353Sdim case LengthModifier::AsLongLong: 280234353Sdim case LengthModifier::AsQuad: 281239462Sdim return ArgType::PtrTo(Ctx.UnsignedLongLongTy); 282261991Sdim case LengthModifier::AsInt64: 283261991Sdim return ArgType::PtrTo(ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")); 284234353Sdim case LengthModifier::AsIntMax: 285239462Sdim return ArgType::PtrTo(ArgType(Ctx.getUIntMaxType(), "uintmax_t")); 286234353Sdim case LengthModifier::AsSizeT: 287239462Sdim return ArgType::PtrTo(ArgType(Ctx.getSizeType(), "size_t")); 288234353Sdim case LengthModifier::AsPtrDiff: 289234353Sdim // FIXME: Unsigned version of ptrdiff_t? 290239462Sdim return ArgType(); 291234353Sdim case LengthModifier::AsLongDouble: 292234353Sdim // GNU extension. 293239462Sdim return ArgType::PtrTo(Ctx.UnsignedLongLongTy); 294239462Sdim case LengthModifier::AsAllocate: 295239462Sdim case LengthModifier::AsMAllocate: 296261991Sdim case LengthModifier::AsInt32: 297261991Sdim case LengthModifier::AsInt3264: 298239462Sdim return ArgType::Invalid(); 299234353Sdim } 300234353Sdim 301234353Sdim // Float. 302234353Sdim case ConversionSpecifier::aArg: 303234353Sdim case ConversionSpecifier::AArg: 304234353Sdim case ConversionSpecifier::eArg: 305234353Sdim case ConversionSpecifier::EArg: 306234353Sdim case ConversionSpecifier::fArg: 307234353Sdim case ConversionSpecifier::FArg: 308234353Sdim case ConversionSpecifier::gArg: 309234353Sdim case ConversionSpecifier::GArg: 310234353Sdim switch (LM.getKind()) { 311239462Sdim case LengthModifier::None: 312239462Sdim return ArgType::PtrTo(Ctx.FloatTy); 313239462Sdim case LengthModifier::AsLong: 314239462Sdim return ArgType::PtrTo(Ctx.DoubleTy); 315234353Sdim case LengthModifier::AsLongDouble: 316239462Sdim return ArgType::PtrTo(Ctx.LongDoubleTy); 317234353Sdim default: 318239462Sdim return ArgType::Invalid(); 319234353Sdim } 320234353Sdim 321234353Sdim // Char, string and scanlist. 322234353Sdim case ConversionSpecifier::cArg: 323234353Sdim case ConversionSpecifier::sArg: 324234353Sdim case ConversionSpecifier::ScanListArg: 325234353Sdim switch (LM.getKind()) { 326239462Sdim case LengthModifier::None: 327239462Sdim return ArgType::PtrTo(ArgType::AnyCharTy); 328234353Sdim case LengthModifier::AsLong: 329261991Sdim return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t")); 330234353Sdim case LengthModifier::AsAllocate: 331234353Sdim case LengthModifier::AsMAllocate: 332239462Sdim return ArgType::PtrTo(ArgType::CStrTy); 333234353Sdim default: 334239462Sdim return ArgType::Invalid(); 335234353Sdim } 336234353Sdim case ConversionSpecifier::CArg: 337234353Sdim case ConversionSpecifier::SArg: 338234353Sdim // FIXME: Mac OS X specific? 339234353Sdim switch (LM.getKind()) { 340234353Sdim case LengthModifier::None: 341261991Sdim return ArgType::PtrTo(ArgType(Ctx.getWideCharType(), "wchar_t")); 342234353Sdim case LengthModifier::AsAllocate: 343234353Sdim case LengthModifier::AsMAllocate: 344239462Sdim return ArgType::PtrTo(ArgType(ArgType::WCStrTy, "wchar_t *")); 345234353Sdim default: 346239462Sdim return ArgType::Invalid(); 347234353Sdim } 348234353Sdim 349234353Sdim // Pointer. 350234353Sdim case ConversionSpecifier::pArg: 351239462Sdim return ArgType::PtrTo(ArgType::CPointerTy); 352234353Sdim 353239462Sdim // Write-back. 354239462Sdim case ConversionSpecifier::nArg: 355239462Sdim switch (LM.getKind()) { 356239462Sdim case LengthModifier::None: 357239462Sdim return ArgType::PtrTo(Ctx.IntTy); 358239462Sdim case LengthModifier::AsChar: 359239462Sdim return ArgType::PtrTo(Ctx.SignedCharTy); 360239462Sdim case LengthModifier::AsShort: 361239462Sdim return ArgType::PtrTo(Ctx.ShortTy); 362239462Sdim case LengthModifier::AsLong: 363239462Sdim return ArgType::PtrTo(Ctx.LongTy); 364239462Sdim case LengthModifier::AsLongLong: 365239462Sdim case LengthModifier::AsQuad: 366239462Sdim return ArgType::PtrTo(Ctx.LongLongTy); 367261991Sdim case LengthModifier::AsInt64: 368261991Sdim return ArgType::PtrTo(ArgType(Ctx.LongLongTy, "__int64")); 369239462Sdim case LengthModifier::AsIntMax: 370239462Sdim return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); 371239462Sdim case LengthModifier::AsSizeT: 372239462Sdim return ArgType(); // FIXME: ssize_t 373239462Sdim case LengthModifier::AsPtrDiff: 374239462Sdim return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); 375239462Sdim case LengthModifier::AsLongDouble: 376239462Sdim return ArgType(); // FIXME: Is this a known extension? 377239462Sdim case LengthModifier::AsAllocate: 378239462Sdim case LengthModifier::AsMAllocate: 379261991Sdim case LengthModifier::AsInt32: 380261991Sdim case LengthModifier::AsInt3264: 381239462Sdim return ArgType::Invalid(); 382239462Sdim } 383239462Sdim 384234353Sdim default: 385234353Sdim break; 386234353Sdim } 387234353Sdim 388239462Sdim return ArgType(); 389234353Sdim} 390234353Sdim 391276479Sdimbool ScanfSpecifier::fixType(QualType QT, QualType RawQT, 392276479Sdim const LangOptions &LangOpt, 393234353Sdim ASTContext &Ctx) { 394234353Sdim 395239462Sdim // %n is different from other conversion specifiers; don't try to fix it. 396239462Sdim if (CS.getKind() == ConversionSpecifier::nArg) 397239462Sdim return false; 398239462Sdim 399276479Sdim if (!QT->isPointerType()) 400276479Sdim return false; 401276479Sdim 402234353Sdim QualType PT = QT->getPointeeType(); 403239462Sdim 404239462Sdim // If it's an enum, get its underlying type. 405276479Sdim if (const EnumType *ETy = PT->getAs<EnumType>()) 406276479Sdim PT = ETy->getDecl()->getIntegerType(); 407276479Sdim 408234353Sdim const BuiltinType *BT = PT->getAs<BuiltinType>(); 409234353Sdim if (!BT) 410234353Sdim return false; 411234353Sdim 412234353Sdim // Pointer to a character. 413234353Sdim if (PT->isAnyCharacterType()) { 414234353Sdim CS.setKind(ConversionSpecifier::sArg); 415234353Sdim if (PT->isWideCharType()) 416234353Sdim LM.setKind(LengthModifier::AsWideChar); 417234353Sdim else 418234353Sdim LM.setKind(LengthModifier::None); 419276479Sdim 420276479Sdim // If we know the target array length, we can use it as a field width. 421276479Sdim if (const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(RawQT)) { 422276479Sdim if (CAT->getSizeModifier() == ArrayType::Normal) 423276479Sdim FieldWidth = OptionalAmount(OptionalAmount::Constant, 424276479Sdim CAT->getSize().getZExtValue() - 1, 425276479Sdim "", 0, false); 426276479Sdim 427276479Sdim } 428234353Sdim return true; 429234353Sdim } 430234353Sdim 431234353Sdim // Figure out the length modifier. 432234353Sdim switch (BT->getKind()) { 433234353Sdim // no modifier 434234353Sdim case BuiltinType::UInt: 435234353Sdim case BuiltinType::Int: 436234353Sdim case BuiltinType::Float: 437234353Sdim LM.setKind(LengthModifier::None); 438234353Sdim break; 439234353Sdim 440234353Sdim // hh 441234353Sdim case BuiltinType::Char_U: 442234353Sdim case BuiltinType::UChar: 443234353Sdim case BuiltinType::Char_S: 444234353Sdim case BuiltinType::SChar: 445234353Sdim LM.setKind(LengthModifier::AsChar); 446234353Sdim break; 447234353Sdim 448234353Sdim // h 449234353Sdim case BuiltinType::Short: 450234353Sdim case BuiltinType::UShort: 451234353Sdim LM.setKind(LengthModifier::AsShort); 452234353Sdim break; 453234353Sdim 454234353Sdim // l 455234353Sdim case BuiltinType::Long: 456234353Sdim case BuiltinType::ULong: 457234353Sdim case BuiltinType::Double: 458234353Sdim LM.setKind(LengthModifier::AsLong); 459234353Sdim break; 460234353Sdim 461234353Sdim // ll 462234353Sdim case BuiltinType::LongLong: 463234353Sdim case BuiltinType::ULongLong: 464234353Sdim LM.setKind(LengthModifier::AsLongLong); 465234353Sdim break; 466234353Sdim 467234353Sdim // L 468234353Sdim case BuiltinType::LongDouble: 469234353Sdim LM.setKind(LengthModifier::AsLongDouble); 470234353Sdim break; 471234353Sdim 472234353Sdim // Don't know. 473234353Sdim default: 474234353Sdim return false; 475234353Sdim } 476234353Sdim 477234353Sdim // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. 478249423Sdim if (isa<TypedefType>(PT) && (LangOpt.C99 || LangOpt.CPlusPlus11)) 479239462Sdim namedTypeToLengthModifier(PT, LM); 480234353Sdim 481234353Sdim // If fixing the length modifier was enough, we are done. 482243830Sdim if (hasValidLengthModifier(Ctx.getTargetInfo())) { 483243830Sdim const analyze_scanf::ArgType &AT = getArgType(Ctx); 484243830Sdim if (AT.isValid() && AT.matchesType(Ctx, QT)) 485243830Sdim return true; 486243830Sdim } 487234353Sdim 488234353Sdim // Figure out the conversion specifier. 489234353Sdim if (PT->isRealFloatingType()) 490234353Sdim CS.setKind(ConversionSpecifier::fArg); 491234353Sdim else if (PT->isSignedIntegerType()) 492234353Sdim CS.setKind(ConversionSpecifier::dArg); 493234353Sdim else if (PT->isUnsignedIntegerType()) 494234353Sdim CS.setKind(ConversionSpecifier::uArg); 495234353Sdim else 496234353Sdim llvm_unreachable("Unexpected type"); 497234353Sdim 498234353Sdim return true; 499234353Sdim} 500234353Sdim 501234353Sdimvoid ScanfSpecifier::toString(raw_ostream &os) const { 502234353Sdim os << "%"; 503234353Sdim 504234353Sdim if (usesPositionalArg()) 505234353Sdim os << getPositionalArgIndex() << "$"; 506234353Sdim if (SuppressAssignment) 507234353Sdim os << "*"; 508234353Sdim 509234353Sdim FieldWidth.toString(os); 510234353Sdim os << LM.toString(); 511234353Sdim os << CS.toString(); 512234353Sdim} 513234353Sdim 514212795Sdimbool clang::analyze_format_string::ParseScanfString(FormatStringHandler &H, 515212795Sdim const char *I, 516234353Sdim const char *E, 517243830Sdim const LangOptions &LO, 518243830Sdim const TargetInfo &Target) { 519212795Sdim 520212795Sdim unsigned argIndex = 0; 521212795Sdim 522212795Sdim // Keep looking for a format specifier until we have exhausted the string. 523212795Sdim while (I != E) { 524234353Sdim const ScanfSpecifierResult &FSR = ParseScanfSpecifier(H, I, E, argIndex, 525243830Sdim LO, Target); 526212795Sdim // Did a fail-stop error of any kind occur when parsing the specifier? 527212795Sdim // If so, don't do any more processing. 528212795Sdim if (FSR.shouldStop()) 529243830Sdim return true; 530212795Sdim // Did we exhaust the string or encounter an error that 531212795Sdim // we can recover from? 532212795Sdim if (!FSR.hasValue()) 533212795Sdim continue; 534212795Sdim // We have a format specifier. Pass it to the callback. 535212795Sdim if (!H.HandleScanfSpecifier(FSR.getValue(), FSR.getStart(), 536212795Sdim I - FSR.getStart())) { 537212795Sdim return true; 538212795Sdim } 539212795Sdim } 540212795Sdim assert(I == E && "Format string not exhausted"); 541212795Sdim return false; 542212795Sdim} 543