FormatString.h 23 KB

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