Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

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