10b57cec5SDimitry Andric //= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines APIs for analyzing the format strings of printf, fscanf, 100b57cec5SDimitry Andric // and friends. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric // The structure of format strings for fprintf are described in C99 7.19.6.1. 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric // The structure of format strings for fscanf are described in C99 7.19.6.2. 150b57cec5SDimitry Andric // 160b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 170b57cec5SDimitry Andric 1804eeddc0SDimitry Andric #ifndef LLVM_CLANG_AST_FORMATSTRING_H 1904eeddc0SDimitry Andric #define LLVM_CLANG_AST_FORMATSTRING_H 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric #include "clang/AST/CanonicalType.h" 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric namespace clang { 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric class TargetInfo; 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 280b57cec5SDimitry Andric /// Common components of both fprintf and fscanf format strings. 290b57cec5SDimitry Andric namespace analyze_format_string { 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric /// Class representing optional flags with location and representation 320b57cec5SDimitry Andric /// information. 330b57cec5SDimitry Andric class OptionalFlag { 340b57cec5SDimitry Andric public: 350b57cec5SDimitry Andric OptionalFlag(const char *Representation) 360b57cec5SDimitry Andric : representation(Representation), flag(false) {} 370b57cec5SDimitry Andric bool isSet() const { return flag; } 380b57cec5SDimitry Andric void set() { flag = true; } 390b57cec5SDimitry Andric void clear() { flag = false; } 400b57cec5SDimitry Andric void setPosition(const char *position) { 410b57cec5SDimitry Andric assert(position); 420b57cec5SDimitry Andric flag = true; 430b57cec5SDimitry Andric this->position = position; 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric const char *getPosition() const { 460b57cec5SDimitry Andric assert(position); 470b57cec5SDimitry Andric return position; 480b57cec5SDimitry Andric } 490b57cec5SDimitry Andric const char *toString() const { return representation; } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric // Overloaded operators for bool like qualities 520b57cec5SDimitry Andric explicit operator bool() const { return flag; } 530b57cec5SDimitry Andric OptionalFlag& operator=(const bool &rhs) { 540b57cec5SDimitry Andric flag = rhs; 550b57cec5SDimitry Andric return *this; // Return a reference to myself. 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric private: 580b57cec5SDimitry Andric const char *representation; 590b57cec5SDimitry Andric const char *position; 600b57cec5SDimitry Andric bool flag; 610b57cec5SDimitry Andric }; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric /// Represents the length modifier in a format string in scanf/printf. 640b57cec5SDimitry Andric class LengthModifier { 650b57cec5SDimitry Andric public: 660b57cec5SDimitry Andric enum Kind { 670b57cec5SDimitry Andric None, 680b57cec5SDimitry Andric AsChar, // 'hh' 690b57cec5SDimitry Andric AsShort, // 'h' 700b57cec5SDimitry Andric AsShortLong, // 'hl' (OpenCL float/int vector element) 710b57cec5SDimitry Andric AsLong, // 'l' 720b57cec5SDimitry Andric AsLongLong, // 'll' 730b57cec5SDimitry Andric AsQuad, // 'q' (BSD, deprecated, for 64-bit integer types) 740b57cec5SDimitry Andric AsIntMax, // 'j' 750b57cec5SDimitry Andric AsSizeT, // 'z' 760b57cec5SDimitry Andric AsPtrDiff, // 't' 770b57cec5SDimitry Andric AsInt32, // 'I32' (MSVCRT, like __int32) 780b57cec5SDimitry Andric AsInt3264, // 'I' (MSVCRT, like __int3264 from MIDL) 790b57cec5SDimitry Andric AsInt64, // 'I64' (MSVCRT, like __int64) 800b57cec5SDimitry Andric AsLongDouble, // 'L' 810b57cec5SDimitry Andric AsAllocate, // for '%as', GNU extension to C90 scanf 820b57cec5SDimitry Andric AsMAllocate, // for '%ms', GNU extension to scanf 830b57cec5SDimitry Andric AsWide, // 'w' (MSVCRT, like l but only for c, C, s, S, or Z 840b57cec5SDimitry Andric AsWideChar = AsLong // for '%ls', only makes sense for printf 850b57cec5SDimitry Andric }; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric LengthModifier() 880b57cec5SDimitry Andric : Position(nullptr), kind(None) {} 890b57cec5SDimitry Andric LengthModifier(const char *pos, Kind k) 900b57cec5SDimitry Andric : Position(pos), kind(k) {} 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric const char *getStart() const { 930b57cec5SDimitry Andric return Position; 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric unsigned getLength() const { 970b57cec5SDimitry Andric switch (kind) { 980b57cec5SDimitry Andric default: 990b57cec5SDimitry Andric return 1; 1000b57cec5SDimitry Andric case AsLongLong: 1010b57cec5SDimitry Andric case AsChar: 1020b57cec5SDimitry Andric return 2; 1030b57cec5SDimitry Andric case AsInt32: 1040b57cec5SDimitry Andric case AsInt64: 1050b57cec5SDimitry Andric return 3; 1060b57cec5SDimitry Andric case None: 1070b57cec5SDimitry Andric return 0; 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric Kind getKind() const { return kind; } 1120b57cec5SDimitry Andric void setKind(Kind k) { kind = k; } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric const char *toString() const; 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric private: 1170b57cec5SDimitry Andric const char *Position; 1180b57cec5SDimitry Andric Kind kind; 1190b57cec5SDimitry Andric }; 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric class ConversionSpecifier { 1220b57cec5SDimitry Andric public: 1230b57cec5SDimitry Andric enum Kind { 1240b57cec5SDimitry Andric InvalidSpecifier = 0, 1250b57cec5SDimitry Andric // C99 conversion specifiers. 1260b57cec5SDimitry Andric cArg, 1270b57cec5SDimitry Andric dArg, 1280b57cec5SDimitry Andric DArg, // Apple extension 1290b57cec5SDimitry Andric iArg, 1300b57cec5SDimitry Andric IntArgBeg = dArg, 1310b57cec5SDimitry Andric IntArgEnd = iArg, 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric oArg, 1340b57cec5SDimitry Andric OArg, // Apple extension 1350b57cec5SDimitry Andric uArg, 1360b57cec5SDimitry Andric UArg, // Apple extension 1370b57cec5SDimitry Andric xArg, 1380b57cec5SDimitry Andric XArg, 1390b57cec5SDimitry Andric UIntArgBeg = oArg, 1400b57cec5SDimitry Andric UIntArgEnd = XArg, 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric fArg, 1430b57cec5SDimitry Andric FArg, 1440b57cec5SDimitry Andric eArg, 1450b57cec5SDimitry Andric EArg, 1460b57cec5SDimitry Andric gArg, 1470b57cec5SDimitry Andric GArg, 1480b57cec5SDimitry Andric aArg, 1490b57cec5SDimitry Andric AArg, 1500b57cec5SDimitry Andric DoubleArgBeg = fArg, 1510b57cec5SDimitry Andric DoubleArgEnd = AArg, 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric sArg, 1540b57cec5SDimitry Andric pArg, 1550b57cec5SDimitry Andric nArg, 1560b57cec5SDimitry Andric PercentArg, 1570b57cec5SDimitry Andric CArg, 1580b57cec5SDimitry Andric SArg, 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric // Apple extension: P specifies to os_log that the data being pointed to is 1610b57cec5SDimitry Andric // to be copied by os_log. The precision indicates the number of bytes to 1620b57cec5SDimitry Andric // copy. 1630b57cec5SDimitry Andric PArg, 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric // ** Printf-specific ** 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric ZArg, // MS extension 1680b57cec5SDimitry Andric 1690b57cec5SDimitry Andric // Objective-C specific specifiers. 1700b57cec5SDimitry Andric ObjCObjArg, // '@' 1710b57cec5SDimitry Andric ObjCBeg = ObjCObjArg, 1720b57cec5SDimitry Andric ObjCEnd = ObjCObjArg, 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric // FreeBSD kernel specific specifiers. 1750b57cec5SDimitry Andric FreeBSDbArg, 1760b57cec5SDimitry Andric FreeBSDDArg, 1770b57cec5SDimitry Andric FreeBSDrArg, 1780b57cec5SDimitry Andric FreeBSDyArg, 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric // GlibC specific specifiers. 1810b57cec5SDimitry Andric PrintErrno, // 'm' 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric PrintfConvBeg = ObjCObjArg, 1840b57cec5SDimitry Andric PrintfConvEnd = PrintErrno, 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric // ** Scanf-specific ** 1870b57cec5SDimitry Andric ScanListArg, // '[' 1880b57cec5SDimitry Andric ScanfConvBeg = ScanListArg, 1890b57cec5SDimitry Andric ScanfConvEnd = ScanListArg 1900b57cec5SDimitry Andric }; 1910b57cec5SDimitry Andric 1920b57cec5SDimitry Andric ConversionSpecifier(bool isPrintf = true) 1930b57cec5SDimitry Andric : IsPrintf(isPrintf), Position(nullptr), EndScanList(nullptr), 1940b57cec5SDimitry Andric kind(InvalidSpecifier) {} 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric ConversionSpecifier(bool isPrintf, const char *pos, Kind k) 1970b57cec5SDimitry Andric : IsPrintf(isPrintf), Position(pos), EndScanList(nullptr), kind(k) {} 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric const char *getStart() const { 2000b57cec5SDimitry Andric return Position; 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric StringRef getCharacters() const { 2040b57cec5SDimitry Andric return StringRef(getStart(), getLength()); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric bool consumesDataArgument() const { 2080b57cec5SDimitry Andric switch (kind) { 2090b57cec5SDimitry Andric case PrintErrno: 2100b57cec5SDimitry Andric assert(IsPrintf); 2110b57cec5SDimitry Andric return false; 2120b57cec5SDimitry Andric case PercentArg: 2130b57cec5SDimitry Andric return false; 2140b57cec5SDimitry Andric case InvalidSpecifier: 2150b57cec5SDimitry Andric return false; 2160b57cec5SDimitry Andric default: 2170b57cec5SDimitry Andric return true; 2180b57cec5SDimitry Andric } 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric Kind getKind() const { return kind; } 2220b57cec5SDimitry Andric void setKind(Kind k) { kind = k; } 2230b57cec5SDimitry Andric unsigned getLength() const { 2240b57cec5SDimitry Andric return EndScanList ? EndScanList - Position : 1; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric void setEndScanList(const char *pos) { EndScanList = pos; } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) || 2290b57cec5SDimitry Andric kind == FreeBSDrArg || kind == FreeBSDyArg; } 2300b57cec5SDimitry Andric bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; } 2310b57cec5SDimitry Andric bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; } 2320b57cec5SDimitry Andric bool isDoubleArg() const { 2330b57cec5SDimitry Andric return kind >= DoubleArgBeg && kind <= DoubleArgEnd; 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric const char *toString() const; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric bool isPrintfKind() const { return IsPrintf; } 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric Optional<ConversionSpecifier> getStandardSpecifier() const; 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric protected: 2430b57cec5SDimitry Andric bool IsPrintf; 2440b57cec5SDimitry Andric const char *Position; 2450b57cec5SDimitry Andric const char *EndScanList; 2460b57cec5SDimitry Andric Kind kind; 2470b57cec5SDimitry Andric }; 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric class ArgType { 2500b57cec5SDimitry Andric public: 2510b57cec5SDimitry Andric enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, 2520b57cec5SDimitry Andric AnyCharTy, CStrTy, WCStrTy, WIntTy }; 2530b57cec5SDimitry Andric 254a7dea167SDimitry Andric /// How well a given conversion specifier matches its argument. 255a7dea167SDimitry Andric enum MatchKind { 256a7dea167SDimitry Andric /// The conversion specifier and the argument types are incompatible. For 257a7dea167SDimitry Andric /// instance, "%d" and float. 258a7dea167SDimitry Andric NoMatch = 0, 259a7dea167SDimitry Andric /// The conversion specifier and the argument type are compatible. For 260a7dea167SDimitry Andric /// instance, "%d" and _Bool. 261a7dea167SDimitry Andric Match = 1, 262a7dea167SDimitry Andric /// The conversion specifier and the argument type are disallowed by the C 263a7dea167SDimitry Andric /// standard, but are in practice harmless. For instance, "%p" and int*. 264a7dea167SDimitry Andric NoMatchPedantic, 265a7dea167SDimitry Andric /// The conversion specifier and the argument type are compatible, but still 266a7dea167SDimitry Andric /// seems likely to be an error. For instance, "%hd" and _Bool. 267a7dea167SDimitry Andric NoMatchTypeConfusion, 268a7dea167SDimitry Andric }; 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric private: 2710b57cec5SDimitry Andric const Kind K; 2720b57cec5SDimitry Andric QualType T; 2730b57cec5SDimitry Andric const char *Name = nullptr; 2740b57cec5SDimitry Andric bool Ptr = false; 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric /// The TypeKind identifies certain well-known types like size_t and 2770b57cec5SDimitry Andric /// ptrdiff_t. 2780b57cec5SDimitry Andric enum class TypeKind { DontCare, SizeT, PtrdiffT }; 2790b57cec5SDimitry Andric TypeKind TK = TypeKind::DontCare; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric public: 2820b57cec5SDimitry Andric ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {} 2830b57cec5SDimitry Andric ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {} 2840b57cec5SDimitry Andric ArgType(CanQualType T) : K(SpecificTy), T(T) {} 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric static ArgType Invalid() { return ArgType(InvalidTy); } 2870b57cec5SDimitry Andric bool isValid() const { return K != InvalidTy; } 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric bool isSizeT() const { return TK == TypeKind::SizeT; } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric /// Create an ArgType which corresponds to the type pointer to A. 2940b57cec5SDimitry Andric static ArgType PtrTo(const ArgType& A) { 2950b57cec5SDimitry Andric assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown"); 2960b57cec5SDimitry Andric ArgType Res = A; 2970b57cec5SDimitry Andric Res.Ptr = true; 2980b57cec5SDimitry Andric return Res; 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric /// Create an ArgType which corresponds to the size_t/ssize_t type. 3020b57cec5SDimitry Andric static ArgType makeSizeT(const ArgType &A) { 3030b57cec5SDimitry Andric ArgType Res = A; 3040b57cec5SDimitry Andric Res.TK = TypeKind::SizeT; 3050b57cec5SDimitry Andric return Res; 3060b57cec5SDimitry Andric } 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric /// Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t 3090b57cec5SDimitry Andric /// type. 3100b57cec5SDimitry Andric static ArgType makePtrdiffT(const ArgType &A) { 3110b57cec5SDimitry Andric ArgType Res = A; 3120b57cec5SDimitry Andric Res.TK = TypeKind::PtrdiffT; 3130b57cec5SDimitry Andric return Res; 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric MatchKind matchesType(ASTContext &C, QualType argTy) const; 3170b57cec5SDimitry Andric 3180b57cec5SDimitry Andric QualType getRepresentativeType(ASTContext &C) const; 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric ArgType makeVectorType(ASTContext &C, unsigned NumElts) const; 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric std::string getRepresentativeTypeName(ASTContext &C) const; 3230b57cec5SDimitry Andric }; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric class OptionalAmount { 3260b57cec5SDimitry Andric public: 3270b57cec5SDimitry Andric enum HowSpecified { NotSpecified, Constant, Arg, Invalid }; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric OptionalAmount(HowSpecified howSpecified, 3300b57cec5SDimitry Andric unsigned amount, 3310b57cec5SDimitry Andric const char *amountStart, 3320b57cec5SDimitry Andric unsigned amountLength, 3330b57cec5SDimitry Andric bool usesPositionalArg) 3340b57cec5SDimitry Andric : start(amountStart), length(amountLength), hs(howSpecified), amt(amount), 33504eeddc0SDimitry Andric UsesPositionalArg(usesPositionalArg), UsesDotPrefix(false) {} 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric OptionalAmount(bool valid = true) 3380b57cec5SDimitry Andric : start(nullptr),length(0), hs(valid ? NotSpecified : Invalid), amt(0), 33904eeddc0SDimitry Andric UsesPositionalArg(false), UsesDotPrefix(false) {} 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric explicit OptionalAmount(unsigned Amount) 3420b57cec5SDimitry Andric : start(nullptr), length(0), hs(Constant), amt(Amount), 3430b57cec5SDimitry Andric UsesPositionalArg(false), UsesDotPrefix(false) {} 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric bool isInvalid() const { 3460b57cec5SDimitry Andric return hs == Invalid; 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric HowSpecified getHowSpecified() const { return hs; } 3500b57cec5SDimitry Andric void setHowSpecified(HowSpecified h) { hs = h; } 3510b57cec5SDimitry Andric 3520b57cec5SDimitry Andric bool hasDataArgument() const { return hs == Arg; } 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric unsigned getArgIndex() const { 3550b57cec5SDimitry Andric assert(hasDataArgument()); 3560b57cec5SDimitry Andric return amt; 3570b57cec5SDimitry Andric } 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric unsigned getConstantAmount() const { 3600b57cec5SDimitry Andric assert(hs == Constant); 3610b57cec5SDimitry Andric return amt; 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric const char *getStart() const { 3650b57cec5SDimitry Andric // We include the . character if it is given. 3660b57cec5SDimitry Andric return start - UsesDotPrefix; 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3690b57cec5SDimitry Andric unsigned getConstantLength() const { 3700b57cec5SDimitry Andric assert(hs == Constant); 3710b57cec5SDimitry Andric return length + UsesDotPrefix; 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric ArgType getArgType(ASTContext &Ctx) const; 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric void toString(raw_ostream &os) const; 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric bool usesPositionalArg() const { return (bool) UsesPositionalArg; } 3790b57cec5SDimitry Andric unsigned getPositionalArgIndex() const { 3800b57cec5SDimitry Andric assert(hasDataArgument()); 3810b57cec5SDimitry Andric return amt + 1; 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric bool usesDotPrefix() const { return UsesDotPrefix; } 3850b57cec5SDimitry Andric void setUsesDotPrefix() { UsesDotPrefix = true; } 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric private: 3880b57cec5SDimitry Andric const char *start; 3890b57cec5SDimitry Andric unsigned length; 3900b57cec5SDimitry Andric HowSpecified hs; 3910b57cec5SDimitry Andric unsigned amt; 3920b57cec5SDimitry Andric bool UsesPositionalArg : 1; 3930b57cec5SDimitry Andric bool UsesDotPrefix; 3940b57cec5SDimitry Andric }; 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric class FormatSpecifier { 3980b57cec5SDimitry Andric protected: 3990b57cec5SDimitry Andric LengthModifier LM; 4000b57cec5SDimitry Andric OptionalAmount FieldWidth; 4010b57cec5SDimitry Andric ConversionSpecifier CS; 4020b57cec5SDimitry Andric OptionalAmount VectorNumElts; 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric /// Positional arguments, an IEEE extension: 4050b57cec5SDimitry Andric /// IEEE Std 1003.1, 2004 Edition 4060b57cec5SDimitry Andric /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html 4070b57cec5SDimitry Andric bool UsesPositionalArg; 4080b57cec5SDimitry Andric unsigned argIndex; 4090b57cec5SDimitry Andric public: 4100b57cec5SDimitry Andric FormatSpecifier(bool isPrintf) 4110b57cec5SDimitry Andric : CS(isPrintf), VectorNumElts(false), 4120b57cec5SDimitry Andric UsesPositionalArg(false), argIndex(0) {} 4130b57cec5SDimitry Andric 4140b57cec5SDimitry Andric void setLengthModifier(LengthModifier lm) { 4150b57cec5SDimitry Andric LM = lm; 4160b57cec5SDimitry Andric } 4170b57cec5SDimitry Andric 4180b57cec5SDimitry Andric void setUsesPositionalArg() { UsesPositionalArg = true; } 4190b57cec5SDimitry Andric 4200b57cec5SDimitry Andric void setArgIndex(unsigned i) { 4210b57cec5SDimitry Andric argIndex = i; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric unsigned getArgIndex() const { 4250b57cec5SDimitry Andric return argIndex; 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric unsigned getPositionalArgIndex() const { 4290b57cec5SDimitry Andric return argIndex + 1; 4300b57cec5SDimitry Andric } 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric const LengthModifier &getLengthModifier() const { 4330b57cec5SDimitry Andric return LM; 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric const OptionalAmount &getFieldWidth() const { 4370b57cec5SDimitry Andric return FieldWidth; 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric void setVectorNumElts(const OptionalAmount &Amt) { 4410b57cec5SDimitry Andric VectorNumElts = Amt; 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric const OptionalAmount &getVectorNumElts() const { 4450b57cec5SDimitry Andric return VectorNumElts; 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric void setFieldWidth(const OptionalAmount &Amt) { 4490b57cec5SDimitry Andric FieldWidth = Amt; 4500b57cec5SDimitry Andric } 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric bool usesPositionalArg() const { return UsesPositionalArg; } 4530b57cec5SDimitry Andric 4540b57cec5SDimitry Andric bool hasValidLengthModifier(const TargetInfo &Target, 4550b57cec5SDimitry Andric const LangOptions &LO) const; 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric bool hasStandardLengthModifier() const; 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric Optional<LengthModifier> getCorrectedLengthModifier() const; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const; 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric bool hasStandardLengthConversionCombination() const; 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric /// For a TypedefType QT, if it is a named integer type such as size_t, 4660b57cec5SDimitry Andric /// assign the appropriate value to LM and return true. 4670b57cec5SDimitry Andric static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM); 4680b57cec5SDimitry Andric }; 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric } // end analyze_format_string namespace 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 4730b57cec5SDimitry Andric /// Pieces specific to fprintf format strings. 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric namespace analyze_printf { 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric class PrintfConversionSpecifier : 4780b57cec5SDimitry Andric public analyze_format_string::ConversionSpecifier { 4790b57cec5SDimitry Andric public: 4800b57cec5SDimitry Andric PrintfConversionSpecifier() 4810b57cec5SDimitry Andric : ConversionSpecifier(true, nullptr, InvalidSpecifier) {} 4820b57cec5SDimitry Andric 4830b57cec5SDimitry Andric PrintfConversionSpecifier(const char *pos, Kind k) 4840b57cec5SDimitry Andric : ConversionSpecifier(true, pos, k) {} 4850b57cec5SDimitry Andric 4860b57cec5SDimitry Andric bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } 4870b57cec5SDimitry Andric bool isDoubleArg() const { return kind >= DoubleArgBeg && 4880b57cec5SDimitry Andric kind <= DoubleArgEnd; } 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric static bool classof(const analyze_format_string::ConversionSpecifier *CS) { 4910b57cec5SDimitry Andric return CS->isPrintfKind(); 4920b57cec5SDimitry Andric } 4930b57cec5SDimitry Andric }; 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric using analyze_format_string::ArgType; 4960b57cec5SDimitry Andric using analyze_format_string::LengthModifier; 4970b57cec5SDimitry Andric using analyze_format_string::OptionalAmount; 4980b57cec5SDimitry Andric using analyze_format_string::OptionalFlag; 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric class PrintfSpecifier : public analyze_format_string::FormatSpecifier { 5010b57cec5SDimitry Andric OptionalFlag HasThousandsGrouping; // ''', POSIX extension. 5020b57cec5SDimitry Andric OptionalFlag IsLeftJustified; // '-' 5030b57cec5SDimitry Andric OptionalFlag HasPlusPrefix; // '+' 5040b57cec5SDimitry Andric OptionalFlag HasSpacePrefix; // ' ' 5050b57cec5SDimitry Andric OptionalFlag HasAlternativeForm; // '#' 5060b57cec5SDimitry Andric OptionalFlag HasLeadingZeroes; // '0' 5070b57cec5SDimitry Andric OptionalFlag HasObjCTechnicalTerm; // '[tt]' 5080b57cec5SDimitry Andric OptionalFlag IsPrivate; // '{private}' 5090b57cec5SDimitry Andric OptionalFlag IsPublic; // '{public}' 5100b57cec5SDimitry Andric OptionalFlag IsSensitive; // '{sensitive}' 5110b57cec5SDimitry Andric OptionalAmount Precision; 5120b57cec5SDimitry Andric StringRef MaskType; 5130b57cec5SDimitry Andric 5140b57cec5SDimitry Andric ArgType getScalarArgType(ASTContext &Ctx, bool IsObjCLiteral) const; 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric public: 5170b57cec5SDimitry Andric PrintfSpecifier() 5180b57cec5SDimitry Andric : FormatSpecifier(/* isPrintf = */ true), HasThousandsGrouping("'"), 5190b57cec5SDimitry Andric IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "), 5200b57cec5SDimitry Andric HasAlternativeForm("#"), HasLeadingZeroes("0"), 5210b57cec5SDimitry Andric HasObjCTechnicalTerm("tt"), IsPrivate("private"), IsPublic("public"), 5220b57cec5SDimitry Andric IsSensitive("sensitive") {} 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric static PrintfSpecifier Parse(const char *beg, const char *end); 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric // Methods for incrementally constructing the PrintfSpecifier. 5270b57cec5SDimitry Andric void setConversionSpecifier(const PrintfConversionSpecifier &cs) { 5280b57cec5SDimitry Andric CS = cs; 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric void setHasThousandsGrouping(const char *position) { 5310b57cec5SDimitry Andric HasThousandsGrouping.setPosition(position); 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric void setIsLeftJustified(const char *position) { 5340b57cec5SDimitry Andric IsLeftJustified.setPosition(position); 5350b57cec5SDimitry Andric } 5360b57cec5SDimitry Andric void setHasPlusPrefix(const char *position) { 5370b57cec5SDimitry Andric HasPlusPrefix.setPosition(position); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric void setHasSpacePrefix(const char *position) { 5400b57cec5SDimitry Andric HasSpacePrefix.setPosition(position); 5410b57cec5SDimitry Andric } 5420b57cec5SDimitry Andric void setHasAlternativeForm(const char *position) { 5430b57cec5SDimitry Andric HasAlternativeForm.setPosition(position); 5440b57cec5SDimitry Andric } 5450b57cec5SDimitry Andric void setHasLeadingZeros(const char *position) { 5460b57cec5SDimitry Andric HasLeadingZeroes.setPosition(position); 5470b57cec5SDimitry Andric } 5480b57cec5SDimitry Andric void setHasObjCTechnicalTerm(const char *position) { 5490b57cec5SDimitry Andric HasObjCTechnicalTerm.setPosition(position); 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric void setIsPrivate(const char *position) { IsPrivate.setPosition(position); } 5520b57cec5SDimitry Andric void setIsPublic(const char *position) { IsPublic.setPosition(position); } 5530b57cec5SDimitry Andric void setIsSensitive(const char *position) { 5540b57cec5SDimitry Andric IsSensitive.setPosition(position); 5550b57cec5SDimitry Andric } 5560b57cec5SDimitry Andric void setUsesPositionalArg() { UsesPositionalArg = true; } 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric // Methods for querying the format specifier. 5590b57cec5SDimitry Andric 5600b57cec5SDimitry Andric const PrintfConversionSpecifier &getConversionSpecifier() const { 5610b57cec5SDimitry Andric return cast<PrintfConversionSpecifier>(CS); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric void setPrecision(const OptionalAmount &Amt) { 5650b57cec5SDimitry Andric Precision = Amt; 5660b57cec5SDimitry Andric Precision.setUsesDotPrefix(); 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric const OptionalAmount &getPrecision() const { 5700b57cec5SDimitry Andric return Precision; 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric bool consumesDataArgument() const { 5740b57cec5SDimitry Andric return getConversionSpecifier().consumesDataArgument(); 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric /// Returns the builtin type that a data argument 5780b57cec5SDimitry Andric /// paired with this format specifier should have. This method 5790b57cec5SDimitry Andric /// will return null if the format specifier does not have 5800b57cec5SDimitry Andric /// a matching data argument or the matching argument matches 5810b57cec5SDimitry Andric /// more than one type. 5820b57cec5SDimitry Andric ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const; 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric const OptionalFlag &hasThousandsGrouping() const { 5850b57cec5SDimitry Andric return HasThousandsGrouping; 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric const OptionalFlag &isLeftJustified() const { return IsLeftJustified; } 5880b57cec5SDimitry Andric const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; } 5890b57cec5SDimitry Andric const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; } 5900b57cec5SDimitry Andric const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; } 5910b57cec5SDimitry Andric const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; } 5920b57cec5SDimitry Andric const OptionalFlag &hasObjCTechnicalTerm() const { return HasObjCTechnicalTerm; } 5930b57cec5SDimitry Andric const OptionalFlag &isPrivate() const { return IsPrivate; } 5940b57cec5SDimitry Andric const OptionalFlag &isPublic() const { return IsPublic; } 5950b57cec5SDimitry Andric const OptionalFlag &isSensitive() const { return IsSensitive; } 5960b57cec5SDimitry Andric bool usesPositionalArg() const { return UsesPositionalArg; } 5970b57cec5SDimitry Andric 5980b57cec5SDimitry Andric StringRef getMaskType() const { return MaskType; } 5990b57cec5SDimitry Andric void setMaskType(StringRef S) { MaskType = S; } 6000b57cec5SDimitry Andric 6010b57cec5SDimitry Andric /// Changes the specifier and length according to a QualType, retaining any 6020b57cec5SDimitry Andric /// flags or options. Returns true on success, or false when a conversion 6030b57cec5SDimitry Andric /// was not successful. 6040b57cec5SDimitry Andric bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx, 6050b57cec5SDimitry Andric bool IsObjCLiteral); 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric void toString(raw_ostream &os) const; 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric // Validation methods - to check if any element results in undefined behavior 6100b57cec5SDimitry Andric bool hasValidPlusPrefix() const; 6110b57cec5SDimitry Andric bool hasValidAlternativeForm() const; 6120b57cec5SDimitry Andric bool hasValidLeadingZeros() const; 6130b57cec5SDimitry Andric bool hasValidSpacePrefix() const; 6140b57cec5SDimitry Andric bool hasValidLeftJustified() const; 6150b57cec5SDimitry Andric bool hasValidThousandsGroupingPrefix() const; 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric bool hasValidPrecision() const; 6180b57cec5SDimitry Andric bool hasValidFieldWidth() const; 6190b57cec5SDimitry Andric }; 6200b57cec5SDimitry Andric } // end analyze_printf namespace 6210b57cec5SDimitry Andric 6220b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6230b57cec5SDimitry Andric /// Pieces specific to fscanf format strings. 6240b57cec5SDimitry Andric 6250b57cec5SDimitry Andric namespace analyze_scanf { 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric class ScanfConversionSpecifier : 6280b57cec5SDimitry Andric public analyze_format_string::ConversionSpecifier { 6290b57cec5SDimitry Andric public: 6300b57cec5SDimitry Andric ScanfConversionSpecifier() 6310b57cec5SDimitry Andric : ConversionSpecifier(false, nullptr, InvalidSpecifier) {} 6320b57cec5SDimitry Andric 6330b57cec5SDimitry Andric ScanfConversionSpecifier(const char *pos, Kind k) 6340b57cec5SDimitry Andric : ConversionSpecifier(false, pos, k) {} 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric static bool classof(const analyze_format_string::ConversionSpecifier *CS) { 6370b57cec5SDimitry Andric return !CS->isPrintfKind(); 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric }; 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric using analyze_format_string::ArgType; 6420b57cec5SDimitry Andric using analyze_format_string::LengthModifier; 6430b57cec5SDimitry Andric using analyze_format_string::OptionalAmount; 6440b57cec5SDimitry Andric using analyze_format_string::OptionalFlag; 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric class ScanfSpecifier : public analyze_format_string::FormatSpecifier { 6470b57cec5SDimitry Andric OptionalFlag SuppressAssignment; // '*' 6480b57cec5SDimitry Andric public: 6490b57cec5SDimitry Andric ScanfSpecifier() : 6500b57cec5SDimitry Andric FormatSpecifier(/* isPrintf = */ false), 6510b57cec5SDimitry Andric SuppressAssignment("*") {} 6520b57cec5SDimitry Andric 6530b57cec5SDimitry Andric void setSuppressAssignment(const char *position) { 6540b57cec5SDimitry Andric SuppressAssignment.setPosition(position); 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric const OptionalFlag &getSuppressAssignment() const { 6580b57cec5SDimitry Andric return SuppressAssignment; 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric void setConversionSpecifier(const ScanfConversionSpecifier &cs) { 6620b57cec5SDimitry Andric CS = cs; 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric const ScanfConversionSpecifier &getConversionSpecifier() const { 6660b57cec5SDimitry Andric return cast<ScanfConversionSpecifier>(CS); 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric bool consumesDataArgument() const { 6700b57cec5SDimitry Andric return CS.consumesDataArgument() && !SuppressAssignment; 6710b57cec5SDimitry Andric } 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andric ArgType getArgType(ASTContext &Ctx) const; 6740b57cec5SDimitry Andric 6750b57cec5SDimitry Andric bool fixType(QualType QT, QualType RawQT, const LangOptions &LangOpt, 6760b57cec5SDimitry Andric ASTContext &Ctx); 6770b57cec5SDimitry Andric 6780b57cec5SDimitry Andric void toString(raw_ostream &os) const; 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric static ScanfSpecifier Parse(const char *beg, const char *end); 6810b57cec5SDimitry Andric }; 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric } // end analyze_scanf namespace 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 6860b57cec5SDimitry Andric // Parsing and processing of format strings (both fprintf and fscanf). 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric namespace analyze_format_string { 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 }; 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric class FormatStringHandler { 6930b57cec5SDimitry Andric public: 6940b57cec5SDimitry Andric FormatStringHandler() {} 6950b57cec5SDimitry Andric virtual ~FormatStringHandler(); 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric virtual void HandleNullChar(const char *nullCharacter) {} 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric virtual void HandlePosition(const char *startPos, unsigned posLen) {} 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, 7020b57cec5SDimitry Andric PositionContext p) {} 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {} 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric virtual void HandleIncompleteSpecifier(const char *startSpecifier, 7070b57cec5SDimitry Andric unsigned specifierLen) {} 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric virtual void HandleEmptyObjCModifierFlag(const char *startFlags, 7100b57cec5SDimitry Andric unsigned flagsLen) {} 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric virtual void HandleInvalidObjCModifierFlag(const char *startFlag, 7130b57cec5SDimitry Andric unsigned flagLen) {} 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric virtual void HandleObjCFlagsWithNonObjCConversion(const char *flagsStart, 7160b57cec5SDimitry Andric const char *flagsEnd, 7170b57cec5SDimitry Andric const char *conversionPosition) {} 7180b57cec5SDimitry Andric // Printf-specific handlers. 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric virtual bool HandleInvalidPrintfConversionSpecifier( 7210b57cec5SDimitry Andric const analyze_printf::PrintfSpecifier &FS, 7220b57cec5SDimitry Andric const char *startSpecifier, 7230b57cec5SDimitry Andric unsigned specifierLen) { 7240b57cec5SDimitry Andric return true; 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, 7280b57cec5SDimitry Andric const char *startSpecifier, 72904eeddc0SDimitry Andric unsigned specifierLen, 73004eeddc0SDimitry Andric const TargetInfo &Target) { 7310b57cec5SDimitry Andric return true; 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric /// Handle mask types whose sizes are not between one and eight bytes. 7350b57cec5SDimitry Andric virtual void handleInvalidMaskType(StringRef MaskType) {} 7360b57cec5SDimitry Andric 7370b57cec5SDimitry Andric // Scanf-specific handlers. 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric virtual bool HandleInvalidScanfConversionSpecifier( 7400b57cec5SDimitry Andric const analyze_scanf::ScanfSpecifier &FS, 7410b57cec5SDimitry Andric const char *startSpecifier, 7420b57cec5SDimitry Andric unsigned specifierLen) { 7430b57cec5SDimitry Andric return true; 7440b57cec5SDimitry Andric } 7450b57cec5SDimitry Andric 7460b57cec5SDimitry Andric virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, 7470b57cec5SDimitry Andric const char *startSpecifier, 7480b57cec5SDimitry Andric unsigned specifierLen) { 7490b57cec5SDimitry Andric return true; 7500b57cec5SDimitry Andric } 7510b57cec5SDimitry Andric 7520b57cec5SDimitry Andric virtual void HandleIncompleteScanList(const char *start, const char *end) {} 7530b57cec5SDimitry Andric }; 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric bool ParsePrintfString(FormatStringHandler &H, 7560b57cec5SDimitry Andric const char *beg, const char *end, const LangOptions &LO, 7570b57cec5SDimitry Andric const TargetInfo &Target, bool isFreeBSDKPrintf); 7580b57cec5SDimitry Andric 7590b57cec5SDimitry Andric bool ParseFormatStringHasSArg(const char *beg, const char *end, 7600b57cec5SDimitry Andric const LangOptions &LO, const TargetInfo &Target); 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric bool ParseScanfString(FormatStringHandler &H, 7630b57cec5SDimitry Andric const char *beg, const char *end, const LangOptions &LO, 7640b57cec5SDimitry Andric const TargetInfo &Target); 7650b57cec5SDimitry Andric 766a7dea167SDimitry Andric /// Return true if the given string has at least one formatting specifier. 767a7dea167SDimitry Andric bool parseFormatStringHasFormattingSpecifiers(const char *Begin, 768a7dea167SDimitry Andric const char *End, 769a7dea167SDimitry Andric const LangOptions &LO, 770a7dea167SDimitry Andric const TargetInfo &Target); 771a7dea167SDimitry Andric 7720b57cec5SDimitry Andric } // end analyze_format_string namespace 7730b57cec5SDimitry Andric } // end clang namespace 7740b57cec5SDimitry Andric #endif 775