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