FormatString.h 23 KB

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