1 //= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines APIs for analyzing the format strings of printf, fscanf, 11 // and friends. 12 // 13 // The structure of format strings for fprintf are described in C99 7.19.6.1. 14 // 15 // The structure of format strings for fscanf are described in C99 7.19.6.2. 16 // 17 //===----------------------------------------------------------------------===// 18 19 #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H 20 #define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H 21 22 #include "clang/AST/CanonicalType.h" 23 24 namespace clang { 25 26 class TargetInfo; 27 28 //===----------------------------------------------------------------------===// 29 /// Common components of both fprintf and fscanf format strings. 30 namespace analyze_format_string { 31 32 /// Class representing optional flags with location and representation 33 /// information. 34 class OptionalFlag { 35 public: OptionalFlag(const char * Representation)36 OptionalFlag(const char *Representation) 37 : representation(Representation), flag(false) {} isSet()38 bool isSet() const { return flag; } set()39 void set() { flag = true; } clear()40 void clear() { flag = false; } setPosition(const char * position)41 void setPosition(const char *position) { 42 assert(position); 43 flag = true; 44 this->position = position; 45 } getPosition()46 const char *getPosition() const { 47 assert(position); 48 return position; 49 } toString()50 const char *toString() const { return representation; } 51 52 // Overloaded operators for bool like qualities 53 explicit operator bool() const { return flag; } 54 OptionalFlag& operator=(const bool &rhs) { 55 flag = rhs; 56 return *this; // Return a reference to myself. 57 } 58 private: 59 const char *representation; 60 const char *position; 61 bool flag; 62 }; 63 64 /// Represents the length modifier in a format string in scanf/printf. 65 class LengthModifier { 66 public: 67 enum Kind { 68 None, 69 AsChar, // 'hh' 70 AsShort, // 'h' 71 AsLong, // 'l' 72 AsLongLong, // 'll' 73 AsQuad, // 'q' (BSD, deprecated, for 64-bit integer types) 74 AsIntMax, // 'j' 75 AsSizeT, // 'z' 76 AsPtrDiff, // 't' 77 AsInt32, // 'I32' (MSVCRT, like __int32) 78 AsInt3264, // 'I' (MSVCRT, like __int3264 from MIDL) 79 AsInt64, // 'I64' (MSVCRT, like __int64) 80 AsLongDouble, // 'L' 81 AsAllocate, // for '%as', GNU extension to C90 scanf 82 AsMAllocate, // for '%ms', GNU extension to scanf 83 AsWide, // 'w' (MSVCRT, like l but only for c, C, s, S, or Z 84 AsWideChar = AsLong // for '%ls', only makes sense for printf 85 }; 86 LengthModifier()87 LengthModifier() 88 : Position(nullptr), kind(None) {} LengthModifier(const char * pos,Kind k)89 LengthModifier(const char *pos, Kind k) 90 : Position(pos), kind(k) {} 91 getStart()92 const char *getStart() const { 93 return Position; 94 } 95 getLength()96 unsigned getLength() const { 97 switch (kind) { 98 default: 99 return 1; 100 case AsLongLong: 101 case AsChar: 102 return 2; 103 case AsInt32: 104 case AsInt64: 105 return 3; 106 case None: 107 return 0; 108 } 109 } 110 getKind()111 Kind getKind() const { return kind; } setKind(Kind k)112 void setKind(Kind k) { kind = k; } 113 114 const char *toString() const; 115 116 private: 117 const char *Position; 118 Kind kind; 119 }; 120 121 class ConversionSpecifier { 122 public: 123 enum Kind { 124 InvalidSpecifier = 0, 125 // C99 conversion specifiers. 126 cArg, 127 dArg, 128 DArg, // Apple extension 129 iArg, 130 IntArgBeg = dArg, 131 IntArgEnd = iArg, 132 133 oArg, 134 OArg, // Apple extension 135 uArg, 136 UArg, // Apple extension 137 xArg, 138 XArg, 139 UIntArgBeg = oArg, 140 UIntArgEnd = XArg, 141 142 fArg, 143 FArg, 144 eArg, 145 EArg, 146 gArg, 147 GArg, 148 aArg, 149 AArg, 150 DoubleArgBeg = fArg, 151 DoubleArgEnd = AArg, 152 153 sArg, 154 pArg, 155 nArg, 156 PercentArg, 157 CArg, 158 SArg, 159 160 // Apple extension: P specifies to os_log that the data being pointed to is 161 // to be copied by os_log. The precision indicates the number of bytes to 162 // copy. 163 PArg, 164 165 // ** Printf-specific ** 166 167 ZArg, // MS extension 168 169 // Objective-C specific specifiers. 170 ObjCObjArg, // '@' 171 ObjCBeg = ObjCObjArg, 172 ObjCEnd = ObjCObjArg, 173 174 // FreeBSD kernel specific specifiers. 175 FreeBSDbArg, 176 FreeBSDDArg, 177 FreeBSDrArg, 178 FreeBSDyArg, 179 180 // GlibC specific specifiers. 181 PrintErrno, // 'm' 182 183 PrintfConvBeg = ObjCObjArg, 184 PrintfConvEnd = PrintErrno, 185 186 // ** Scanf-specific ** 187 ScanListArg, // '[' 188 ScanfConvBeg = ScanListArg, 189 ScanfConvEnd = ScanListArg 190 }; 191 192 ConversionSpecifier(bool isPrintf = true) IsPrintf(isPrintf)193 : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr), 194 kind(InvalidSpecifier) {} 195 ConversionSpecifier(bool isPrintf,const char * pos,Kind k)196 ConversionSpecifier(bool isPrintf, const char *pos, Kind k) 197 : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {} 198 getStart()199 const char *getStart() const { 200 return Position; 201 } 202 getCharacters()203 StringRef getCharacters() const { 204 return StringRef(getStart(), getLength()); 205 } 206 consumesDataArgument()207 bool consumesDataArgument() const { 208 switch (kind) { 209 case PrintErrno: 210 assert(IsPrintf); 211 return false; 212 case PercentArg: 213 return false; 214 case InvalidSpecifier: 215 return false; 216 default: 217 return true; 218 } 219 } 220 getKind()221 Kind getKind() const { return kind; } setKind(Kind k)222 void setKind(Kind k) { kind = k; } getLength()223 unsigned getLength() const { 224 return EndScanList ? EndScanList - Position : 1; 225 } setEndScanList(const char * pos)226 void setEndScanList(const char *pos) { EndScanList = pos; } 227 isIntArg()228 bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) || 229 kind == FreeBSDrArg || kind == FreeBSDyArg; } isUIntArg()230 bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; } isAnyIntArg()231 bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; } isDoubleArg()232 bool isDoubleArg() const { 233 return kind >= DoubleArgBeg && kind <= DoubleArgEnd; 234 } 235 236 const char *toString() const; 237 isPrintfKind()238 bool isPrintfKind() const { return IsPrintf; } 239 240 Optional<ConversionSpecifier> getStandardSpecifier() const; 241 242 protected: 243 bool IsPrintf; 244 const char *Position; 245 const char *EndScanList; 246 Kind kind; 247 }; 248 249 class ArgType { 250 public: 251 enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, 252 AnyCharTy, CStrTy, WCStrTy, WIntTy }; 253 254 enum MatchKind { NoMatch = 0, Match = 1, NoMatchPedantic }; 255 256 private: 257 const Kind K; 258 QualType T; 259 const char *Name = nullptr; 260 bool Ptr = false; 261 262 /// The TypeKind identifies certain well-known types like size_t and 263 /// ptrdiff_t. 264 enum class TypeKind { DontCare, SizeT, PtrdiffT }; 265 TypeKind TK = TypeKind::DontCare; 266 267 public: K(K)268 ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {} K(SpecificTy)269 ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {} ArgType(CanQualType T)270 ArgType(CanQualType T) : K(SpecificTy), T(T) {} 271 Invalid()272 static ArgType Invalid() { return ArgType(InvalidTy); } isValid()273 bool isValid() const { return K != InvalidTy; } 274 isSizeT()275 bool isSizeT() const { return TK == TypeKind::SizeT; } 276 isPtrdiffT()277 bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; } 278 279 /// Create an ArgType which corresponds to the type pointer to A. PtrTo(const ArgType & A)280 static ArgType PtrTo(const ArgType& A) { 281 assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown"); 282 ArgType Res = A; 283 Res.Ptr = true; 284 return Res; 285 } 286 287 /// Create an ArgType which corresponds to the size_t/ssize_t type. makeSizeT(const ArgType & A)288 static ArgType makeSizeT(const ArgType &A) { 289 ArgType Res = A; 290 Res.TK = TypeKind::SizeT; 291 return Res; 292 } 293 294 /// Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t 295 /// type. makePtrdiffT(const ArgType & A)296 static ArgType makePtrdiffT(const ArgType &A) { 297 ArgType Res = A; 298 Res.TK = TypeKind::PtrdiffT; 299 return Res; 300 } 301 302 MatchKind matchesType(ASTContext &C, QualType argTy) const; 303 304 QualType getRepresentativeType(ASTContext &C) const; 305 306 std::string getRepresentativeTypeName(ASTContext &C) const; 307 }; 308 309 class OptionalAmount { 310 public: 311 enum HowSpecified { NotSpecified, Constant, Arg, Invalid }; 312 OptionalAmount(HowSpecified howSpecified,unsigned amount,const char * amountStart,unsigned amountLength,bool usesPositionalArg)313 OptionalAmount(HowSpecified howSpecified, 314 unsigned amount, 315 const char *amountStart, 316 unsigned amountLength, 317 bool usesPositionalArg) 318 : start(amountStart), length(amountLength), hs(howSpecified), amt(amount), 319 UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {} 320 321 OptionalAmount(bool valid = true) start(nullptr)322 : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0), 323 UsesPositionalArg(0), UsesDotPrefix(0) {} 324 isInvalid()325 bool isInvalid() const { 326 return hs == Invalid; 327 } 328 getHowSpecified()329 HowSpecified getHowSpecified() const { return hs; } setHowSpecified(HowSpecified h)330 void setHowSpecified(HowSpecified h) { hs = h; } 331 hasDataArgument()332 bool hasDataArgument() const { return hs == Arg; } 333 getArgIndex()334 unsigned getArgIndex() const { 335 assert(hasDataArgument()); 336 return amt; 337 } 338 getConstantAmount()339 unsigned getConstantAmount() const { 340 assert(hs == Constant); 341 return amt; 342 } 343 getStart()344 const char *getStart() const { 345 // We include the . character if it is given. 346 return start - UsesDotPrefix; 347 } 348 getConstantLength()349 unsigned getConstantLength() const { 350 assert(hs == Constant); 351 return length + UsesDotPrefix; 352 } 353 354 ArgType getArgType(ASTContext &Ctx) const; 355 356 void toString(raw_ostream &os) const; 357 usesPositionalArg()358 bool usesPositionalArg() const { return (bool) UsesPositionalArg; } getPositionalArgIndex()359 unsigned getPositionalArgIndex() const { 360 assert(hasDataArgument()); 361 return amt + 1; 362 } 363 usesDotPrefix()364 bool usesDotPrefix() const { return UsesDotPrefix; } setUsesDotPrefix()365 void setUsesDotPrefix() { UsesDotPrefix = true; } 366 367 private: 368 const char *start; 369 unsigned length; 370 HowSpecified hs; 371 unsigned amt; 372 bool UsesPositionalArg : 1; 373 bool UsesDotPrefix; 374 }; 375 376 377 class FormatSpecifier { 378 protected: 379 LengthModifier LM; 380 OptionalAmount FieldWidth; 381 ConversionSpecifier CS; 382 /// Positional arguments, an IEEE extension: 383 /// IEEE Std 1003.1, 2004 Edition 384 /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html 385 bool UsesPositionalArg; 386 unsigned argIndex; 387 public: FormatSpecifier(bool isPrintf)388 FormatSpecifier(bool isPrintf) 389 : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {} 390 setLengthModifier(LengthModifier lm)391 void setLengthModifier(LengthModifier lm) { 392 LM = lm; 393 } 394 setUsesPositionalArg()395 void setUsesPositionalArg() { UsesPositionalArg = true; } 396 setArgIndex(unsigned i)397 void setArgIndex(unsigned i) { 398 argIndex = i; 399 } 400 getArgIndex()401 unsigned getArgIndex() const { 402 return argIndex; 403 } 404 getPositionalArgIndex()405 unsigned getPositionalArgIndex() const { 406 return argIndex + 1; 407 } 408 getLengthModifier()409 const LengthModifier &getLengthModifier() const { 410 return LM; 411 } 412 getFieldWidth()413 const OptionalAmount &getFieldWidth() const { 414 return FieldWidth; 415 } 416 setFieldWidth(const OptionalAmount & Amt)417 void setFieldWidth(const OptionalAmount &Amt) { 418 FieldWidth = Amt; 419 } 420 usesPositionalArg()421 bool usesPositionalArg() const { return UsesPositionalArg; } 422 423 bool hasValidLengthModifier(const TargetInfo &Target) const; 424 425 bool hasStandardLengthModifier() const; 426 427 Optional<LengthModifier> getCorrectedLengthModifier() const; 428 429 bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; 430 431 bool hasStandardLengthConversionCombination() const; 432 433 /// For a TypedefType QT, if it is a named integer type such as size_t, 434 /// assign the appropriate value to LM and return true. 435 static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM); 436 }; 437 438 } // end analyze_format_string namespace 439 440 //===----------------------------------------------------------------------===// 441 /// Pieces specific to fprintf format strings. 442 443 namespace analyze_printf { 444 445 class PrintfConversionSpecifier : 446 public analyze_format_string::ConversionSpecifier { 447 public: PrintfConversionSpecifier()448 PrintfConversionSpecifier() 449 : ConversionSpecifier(true, nullptr, InvalidSpecifier) {} 450 PrintfConversionSpecifier(const char * pos,Kind k)451 PrintfConversionSpecifier(const char *pos, Kind k) 452 : ConversionSpecifier(true, pos, k) {} 453 isObjCArg()454 bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } isDoubleArg()455 bool isDoubleArg() const { return kind >= DoubleArgBeg && 456 kind <= DoubleArgEnd; } 457 classof(const analyze_format_string::ConversionSpecifier * CS)458 static bool classof(const analyze_format_string::ConversionSpecifier *CS) { 459 return CS->isPrintfKind(); 460 } 461 }; 462 463 using analyze_format_string::ArgType; 464 using analyze_format_string::LengthModifier; 465 using analyze_format_string::OptionalAmount; 466 using analyze_format_string::OptionalFlag; 467 468 class PrintfSpecifier : public analyze_format_string::FormatSpecifier { 469 OptionalFlag HasThousandsGrouping; // ''', POSIX extension. 470 OptionalFlag IsLeftJustified; // '-' 471 OptionalFlag HasPlusPrefix; // '+' 472 OptionalFlag HasSpacePrefix; // ' ' 473 OptionalFlag HasAlternativeForm; // '#' 474 OptionalFlag HasLeadingZeroes; // '0' 475 OptionalFlag HasObjCTechnicalTerm; // '[tt]' 476 OptionalFlag IsPrivate; // '{private}' 477 OptionalFlag IsPublic; // '{public}' 478 OptionalAmount Precision; 479 public: PrintfSpecifier()480 PrintfSpecifier() 481 : FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"), 482 IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "), 483 HasAlternativeForm("#"), HasLeadingZeroes("0"), 484 HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public") {} 485 486 static PrintfSpecifier Parse(const char *beg, const char *end); 487 488 // Methods for incrementally constructing the PrintfSpecifier. setConversionSpecifier(const PrintfConversionSpecifier & cs)489 void setConversionSpecifier(const PrintfConversionSpecifier &cs) { 490 CS = cs; 491 } setHasThousandsGrouping(const char * position)492 void setHasThousandsGrouping(const char *position) { 493 HasThousandsGrouping.setPosition(position); 494 } setIsLeftJustified(const char * position)495 void setIsLeftJustified(const char *position) { 496 IsLeftJustified.setPosition(position); 497 } setHasPlusPrefix(const char * position)498 void setHasPlusPrefix(const char *position) { 499 HasPlusPrefix.setPosition(position); 500 } setHasSpacePrefix(const char * position)501 void setHasSpacePrefix(const char *position) { 502 HasSpacePrefix.setPosition(position); 503 } setHasAlternativeForm(const char * position)504 void setHasAlternativeForm(const char *position) { 505 HasAlternativeForm.setPosition(position); 506 } setHasLeadingZeros(const char * position)507 void setHasLeadingZeros(const char *position) { 508 HasLeadingZeroes.setPosition(position); 509 } setHasObjCTechnicalTerm(const char * position)510 void setHasObjCTechnicalTerm(const char *position) { 511 HasObjCTechnicalTerm.setPosition(position); 512 } setIsPrivate(const char * position)513 void setIsPrivate(const char *position) { IsPrivate.setPosition(position); } setIsPublic(const char * position)514 void setIsPublic(const char *position) { IsPublic.setPosition(position); } setUsesPositionalArg()515 void setUsesPositionalArg() { UsesPositionalArg = true; } 516 517 // Methods for querying the format specifier. 518 getConversionSpecifier()519 const PrintfConversionSpecifier &getConversionSpecifier() const { 520 return cast<PrintfConversionSpecifier>(CS); 521 } 522 setPrecision(const OptionalAmount & Amt)523 void setPrecision(const OptionalAmount &Amt) { 524 Precision = Amt; 525 Precision.setUsesDotPrefix(); 526 } 527 getPrecision()528 const OptionalAmount &getPrecision() const { 529 return Precision; 530 } 531 consumesDataArgument()532 bool consumesDataArgument() const { 533 return getConversionSpecifier().consumesDataArgument(); 534 } 535 536 /// Returns the builtin type that a data argument 537 /// paired with this format specifier should have. This method 538 /// will return null if the format specifier does not have 539 /// a matching data argument or the matching argument matches 540 /// more than one type. 541 ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const; 542 hasThousandsGrouping()543 const OptionalFlag &hasThousandsGrouping() const { 544 return HasThousandsGrouping; 545 } isLeftJustified()546 const OptionalFlag &isLeftJustified() const { return IsLeftJustified; } hasPlusPrefix()547 const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; } hasAlternativeForm()548 const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; } hasLeadingZeros()549 const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; } hasSpacePrefix()550 const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; } hasObjCTechnicalTerm()551 const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; } isPrivate()552 const OptionalFlag &isPrivate() const { return IsPrivate; } isPublic()553 const OptionalFlag &isPublic() const { return IsPublic; } usesPositionalArg()554 bool usesPositionalArg() const { return UsesPositionalArg; } 555 556 /// Changes the specifier and length according to a QualType, retaining any 557 /// flags or options. Returns true on success, or false when a conversion 558 /// was not successful. 559 bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx, 560 bool IsObjCLiteral); 561 562 void toString(raw_ostream &os) const; 563 564 // Validation methods - to check if any element results in undefined behavior 565 bool hasValidPlusPrefix() const; 566 bool hasValidAlternativeForm() const; 567 bool hasValidLeadingZeros() const; 568 bool hasValidSpacePrefix() const; 569 bool hasValidLeftJustified() const; 570 bool hasValidThousandsGroupingPrefix() const; 571 572 bool hasValidPrecision() const; 573 bool hasValidFieldWidth() const; 574 }; 575 } // end analyze_printf namespace 576 577 //===----------------------------------------------------------------------===// 578 /// Pieces specific to fscanf format strings. 579 580 namespace analyze_scanf { 581 582 class ScanfConversionSpecifier : 583 public analyze_format_string::ConversionSpecifier { 584 public: ScanfConversionSpecifier()585 ScanfConversionSpecifier() 586 : ConversionSpecifier(false, nullptr, InvalidSpecifier) {} 587 ScanfConversionSpecifier(const char * pos,Kind k)588 ScanfConversionSpecifier(const char *pos, Kind k) 589 : ConversionSpecifier(false, pos, k) {} 590 classof(const analyze_format_string::ConversionSpecifier * CS)591 static bool classof(const analyze_format_string::ConversionSpecifier *CS) { 592 return !CS->isPrintfKind(); 593 } 594 }; 595 596 using analyze_format_string::ArgType; 597 using analyze_format_string::LengthModifier; 598 using analyze_format_string::OptionalAmount; 599 using analyze_format_string::OptionalFlag; 600 601 class ScanfSpecifier : public analyze_format_string::FormatSpecifier { 602 OptionalFlag SuppressAssignment; // '*' 603 public: ScanfSpecifier()604 ScanfSpecifier() : 605 FormatSpecifier(/* isPrintf = */ false), 606 SuppressAssignment("*") {} 607 setSuppressAssignment(const char * position)608 void setSuppressAssignment(const char *position) { 609 SuppressAssignment.setPosition(position); 610 } 611 getSuppressAssignment()612 const OptionalFlag &getSuppressAssignment() const { 613 return SuppressAssignment; 614 } 615 setConversionSpecifier(const ScanfConversionSpecifier & cs)616 void setConversionSpecifier(const ScanfConversionSpecifier &cs) { 617 CS = cs; 618 } 619 getConversionSpecifier()620 const ScanfConversionSpecifier &getConversionSpecifier() const { 621 return cast<ScanfConversionSpecifier>(CS); 622 } 623 consumesDataArgument()624 bool consumesDataArgument() const { 625 return CS.consumesDataArgument() && !SuppressAssignment; 626 } 627 628 ArgType getArgType(ASTContext &Ctx) const; 629 630 bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt, 631 ASTContext &Ctx); 632 633 void toString(raw_ostream &os) const; 634 635 static ScanfSpecifier Parse(const char *beg, const char *end); 636 }; 637 638 } // end analyze_scanf namespace 639 640 //===----------------------------------------------------------------------===// 641 // Parsing and processing of format strings (both fprintf and fscanf). 642 643 namespace analyze_format_string { 644 645 enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 }; 646 647 class FormatStringHandler { 648 public: FormatStringHandler()649 FormatStringHandler() {} 650 virtual ~FormatStringHandler(); 651 HandleNullChar(const char * nullCharacter)652 virtual void HandleNullChar(const char *nullCharacter) {} 653 HandlePosition(const char * startPos,unsigned posLen)654 virtual void HandlePosition(const char *startPos, unsigned posLen) {} 655 HandleInvalidPosition(const char * startPos,unsigned posLen,PositionContext p)656 virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, 657 PositionContext p) {} 658 HandleZeroPosition(const char * startPos,unsigned posLen)659 virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {} 660 HandleIncompleteSpecifier(const char * startSpecifier,unsigned specifierLen)661 virtual void HandleIncompleteSpecifier(const char *startSpecifier, 662 unsigned specifierLen) {} 663 HandleEmptyObjCModifierFlag(const char * startFlags,unsigned flagsLen)664 virtual void HandleEmptyObjCModifierFlag(const char *startFlags, 665 unsigned flagsLen) {} 666 HandleInvalidObjCModifierFlag(const char * startFlag,unsigned flagLen)667 virtual void HandleInvalidObjCModifierFlag(const char *startFlag, 668 unsigned flagLen) {} 669 HandleObjCFlagsWithNonObjCConversion(const char * flagsStart,const char * flagsEnd,const char * conversionPosition)670 virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart, 671 const char *flagsEnd, 672 const char *conversionPosition) {} 673 // Printf-specific handlers. 674 HandleInvalidPrintfConversionSpecifier(const analyze_printf::PrintfSpecifier & FS,const char * startSpecifier,unsigned specifierLen)675 virtual bool HandleInvalidPrintfConversionSpecifier( 676 const analyze_printf::PrintfSpecifier &FS, 677 const char *startSpecifier, 678 unsigned specifierLen) { 679 return true; 680 } 681 HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier & FS,const char * startSpecifier,unsigned specifierLen)682 virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, 683 const char *startSpecifier, 684 unsigned specifierLen) { 685 return true; 686 } 687 688 // Scanf-specific handlers. 689 HandleInvalidScanfConversionSpecifier(const analyze_scanf::ScanfSpecifier & FS,const char * startSpecifier,unsigned specifierLen)690 virtual bool HandleInvalidScanfConversionSpecifier( 691 const analyze_scanf::ScanfSpecifier &FS, 692 const char *startSpecifier, 693 unsigned specifierLen) { 694 return true; 695 } 696 HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier & FS,const char * startSpecifier,unsigned specifierLen)697 virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, 698 const char *startSpecifier, 699 unsigned specifierLen) { 700 return true; 701 } 702 HandleIncompleteScanList(const char * start,const char * end)703 virtual void HandleIncompleteScanList(const char *start, const char *end) {} 704 }; 705 706 bool ParsePrintfString(FormatStringHandler &H, 707 const char *beg, const char *end, const LangOptions &LO, 708 const TargetInfo &Target, bool isFreeBSDKPrintf); 709 710 bool ParseFormatStringHasSArg(const char *beg, const char *end, 711 const LangOptions &LO, const TargetInfo &Target); 712 713 bool ParseScanfString(FormatStringHandler &H, 714 const char *beg, const char *end, const LangOptions &LO, 715 const TargetInfo &Target); 716 717 } // end analyze_format_string namespace 718 } // end clang namespace 719 #endif 720