PrintfFormatString.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // Handling of format string in printf and friends. The structure of format
  11. // strings for fprintf() are described in C99 7.19.6.1.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #include "clang/Analysis/Analyses/FormatString.h"
  15. #include "FormatStringParsing.h"
  16. using clang::analyze_format_string::ArgType;
  17. using clang::analyze_format_string::FormatStringHandler;
  18. using clang::analyze_format_string::LengthModifier;
  19. using clang::analyze_format_string::OptionalAmount;
  20. using clang::analyze_format_string::ConversionSpecifier;
  21. using clang::analyze_printf::PrintfSpecifier;
  22. using namespace clang;
  23. typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
  24. PrintfSpecifierResult;
  25. //===----------------------------------------------------------------------===//
  26. // Methods for parsing format strings.
  27. //===----------------------------------------------------------------------===//
  28. using analyze_format_string::ParseNonPositionAmount;
  29. static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
  30. const char *Start, const char *&Beg, const char *E,
  31. unsigned *argIndex) {
  32. if (argIndex) {
  33. FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
  34. } else {
  35. const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
  36. analyze_format_string::PrecisionPos);
  37. if (Amt.isInvalid())
  38. return true;
  39. FS.setPrecision(Amt);
  40. }
  41. return false;
  42. }
  43. static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
  44. const char *&Beg,
  45. const char *E,
  46. unsigned &argIndex,
  47. const LangOptions &LO) {
  48. using namespace clang::analyze_format_string;
  49. using namespace clang::analyze_printf;
  50. const char *I = Beg;
  51. const char *Start = 0;
  52. UpdateOnReturn <const char*> UpdateBeg(Beg, I);
  53. // Look for a '%' character that indicates the start of a format specifier.
  54. for ( ; I != E ; ++I) {
  55. char c = *I;
  56. if (c == '\0') {
  57. // Detect spurious null characters, which are likely errors.
  58. H.HandleNullChar(I);
  59. return true;
  60. }
  61. if (c == '%') {
  62. Start = I++; // Record the start of the format specifier.
  63. break;
  64. }
  65. }
  66. // No format specifier found?
  67. if (!Start)
  68. return false;
  69. if (I == E) {
  70. // No more characters left?
  71. H.HandleIncompleteSpecifier(Start, E - Start);
  72. return true;
  73. }
  74. PrintfSpecifier FS;
  75. if (ParseArgPosition(H, FS, Start, I, E))
  76. return true;
  77. if (I == E) {
  78. // No more characters left?
  79. H.HandleIncompleteSpecifier(Start, E - Start);
  80. return true;
  81. }
  82. // Look for flags (if any).
  83. bool hasMore = true;
  84. for ( ; I != E; ++I) {
  85. switch (*I) {
  86. default: hasMore = false; break;
  87. case '\'':
  88. // FIXME: POSIX specific. Always accept?
  89. FS.setHasThousandsGrouping(I);
  90. break;
  91. case '-': FS.setIsLeftJustified(I); break;
  92. case '+': FS.setHasPlusPrefix(I); break;
  93. case ' ': FS.setHasSpacePrefix(I); break;
  94. case '#': FS.setHasAlternativeForm(I); break;
  95. case '0': FS.setHasLeadingZeros(I); break;
  96. }
  97. if (!hasMore)
  98. break;
  99. }
  100. if (I == E) {
  101. // No more characters left?
  102. H.HandleIncompleteSpecifier(Start, E - Start);
  103. return true;
  104. }
  105. // Look for the field width (if any).
  106. if (ParseFieldWidth(H, FS, Start, I, E,
  107. FS.usesPositionalArg() ? 0 : &argIndex))
  108. return true;
  109. if (I == E) {
  110. // No more characters left?
  111. H.HandleIncompleteSpecifier(Start, E - Start);
  112. return true;
  113. }
  114. // Look for the precision (if any).
  115. if (*I == '.') {
  116. ++I;
  117. if (I == E) {
  118. H.HandleIncompleteSpecifier(Start, E - Start);
  119. return true;
  120. }
  121. if (ParsePrecision(H, FS, Start, I, E,
  122. FS.usesPositionalArg() ? 0 : &argIndex))
  123. return true;
  124. if (I == E) {
  125. // No more characters left?
  126. H.HandleIncompleteSpecifier(Start, E - Start);
  127. return true;
  128. }
  129. }
  130. // Look for the length modifier.
  131. if (ParseLengthModifier(FS, I, E, LO) && I == E) {
  132. // No more characters left?
  133. H.HandleIncompleteSpecifier(Start, E - Start);
  134. return true;
  135. }
  136. if (*I == '\0') {
  137. // Detect spurious null characters, which are likely errors.
  138. H.HandleNullChar(I);
  139. return true;
  140. }
  141. // Finally, look for the conversion specifier.
  142. const char *conversionPosition = I++;
  143. ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
  144. switch (*conversionPosition) {
  145. default:
  146. break;
  147. // C99: 7.19.6.1 (section 8).
  148. case '%': k = ConversionSpecifier::PercentArg; break;
  149. case 'A': k = ConversionSpecifier::AArg; break;
  150. case 'E': k = ConversionSpecifier::EArg; break;
  151. case 'F': k = ConversionSpecifier::FArg; break;
  152. case 'G': k = ConversionSpecifier::GArg; break;
  153. case 'X': k = ConversionSpecifier::XArg; break;
  154. case 'a': k = ConversionSpecifier::aArg; break;
  155. case 'c': k = ConversionSpecifier::cArg; break;
  156. case 'd': k = ConversionSpecifier::dArg; break;
  157. case 'e': k = ConversionSpecifier::eArg; break;
  158. case 'f': k = ConversionSpecifier::fArg; break;
  159. case 'g': k = ConversionSpecifier::gArg; break;
  160. case 'i': k = ConversionSpecifier::iArg; break;
  161. case 'n': k = ConversionSpecifier::nArg; break;
  162. case 'o': k = ConversionSpecifier::oArg; break;
  163. case 'p': k = ConversionSpecifier::pArg; break;
  164. case 's': k = ConversionSpecifier::sArg; break;
  165. case 'u': k = ConversionSpecifier::uArg; break;
  166. case 'x': k = ConversionSpecifier::xArg; break;
  167. // POSIX specific.
  168. case 'C': k = ConversionSpecifier::CArg; break;
  169. case 'S': k = ConversionSpecifier::SArg; break;
  170. // Objective-C.
  171. case '@': k = ConversionSpecifier::ObjCObjArg; break;
  172. // Glibc specific.
  173. case 'm': k = ConversionSpecifier::PrintErrno; break;
  174. }
  175. PrintfConversionSpecifier CS(conversionPosition, k);
  176. FS.setConversionSpecifier(CS);
  177. if (CS.consumesDataArgument() && !FS.usesPositionalArg())
  178. FS.setArgIndex(argIndex++);
  179. if (k == ConversionSpecifier::InvalidSpecifier) {
  180. // Assume the conversion takes one argument.
  181. return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
  182. }
  183. return PrintfSpecifierResult(Start, FS);
  184. }
  185. bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
  186. const char *I,
  187. const char *E,
  188. const LangOptions &LO) {
  189. unsigned argIndex = 0;
  190. // Keep looking for a format specifier until we have exhausted the string.
  191. while (I != E) {
  192. const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
  193. LO);
  194. // Did a fail-stop error of any kind occur when parsing the specifier?
  195. // If so, don't do any more processing.
  196. if (FSR.shouldStop())
  197. return true;;
  198. // Did we exhaust the string or encounter an error that
  199. // we can recover from?
  200. if (!FSR.hasValue())
  201. continue;
  202. // We have a format specifier. Pass it to the callback.
  203. if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
  204. I - FSR.getStart()))
  205. return true;
  206. }
  207. assert(I == E && "Format string not exhausted");
  208. return false;
  209. }
  210. //===----------------------------------------------------------------------===//
  211. // Methods on PrintfSpecifier.
  212. //===----------------------------------------------------------------------===//
  213. ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
  214. bool IsObjCLiteral) const {
  215. const PrintfConversionSpecifier &CS = getConversionSpecifier();
  216. if (!CS.consumesDataArgument())
  217. return ArgType::Invalid();
  218. if (CS.getKind() == ConversionSpecifier::cArg)
  219. switch (LM.getKind()) {
  220. case LengthModifier::None: return Ctx.IntTy;
  221. case LengthModifier::AsLong:
  222. return ArgType(ArgType::WIntTy, "wint_t");
  223. default:
  224. return ArgType::Invalid();
  225. }
  226. if (CS.isIntArg())
  227. switch (LM.getKind()) {
  228. case LengthModifier::AsLongDouble:
  229. // GNU extension.
  230. return Ctx.LongLongTy;
  231. case LengthModifier::None: return Ctx.IntTy;
  232. case LengthModifier::AsChar: return ArgType::AnyCharTy;
  233. case LengthModifier::AsShort: return Ctx.ShortTy;
  234. case LengthModifier::AsLong: return Ctx.LongTy;
  235. case LengthModifier::AsLongLong:
  236. case LengthModifier::AsQuad:
  237. return Ctx.LongLongTy;
  238. case LengthModifier::AsIntMax:
  239. return ArgType(Ctx.getIntMaxType(), "intmax_t");
  240. case LengthModifier::AsSizeT:
  241. // FIXME: How to get the corresponding signed version of size_t?
  242. return ArgType();
  243. case LengthModifier::AsPtrDiff:
  244. return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
  245. case LengthModifier::AsAllocate:
  246. case LengthModifier::AsMAllocate:
  247. return ArgType::Invalid();
  248. }
  249. if (CS.isUIntArg())
  250. switch (LM.getKind()) {
  251. case LengthModifier::AsLongDouble:
  252. // GNU extension.
  253. return Ctx.UnsignedLongLongTy;
  254. case LengthModifier::None: return Ctx.UnsignedIntTy;
  255. case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
  256. case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
  257. case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
  258. case LengthModifier::AsLongLong:
  259. case LengthModifier::AsQuad:
  260. return Ctx.UnsignedLongLongTy;
  261. case LengthModifier::AsIntMax:
  262. return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
  263. case LengthModifier::AsSizeT:
  264. return ArgType(Ctx.getSizeType(), "size_t");
  265. case LengthModifier::AsPtrDiff:
  266. // FIXME: How to get the corresponding unsigned
  267. // version of ptrdiff_t?
  268. return ArgType();
  269. case LengthModifier::AsAllocate:
  270. case LengthModifier::AsMAllocate:
  271. return ArgType::Invalid();
  272. }
  273. if (CS.isDoubleArg()) {
  274. if (LM.getKind() == LengthModifier::AsLongDouble)
  275. return Ctx.LongDoubleTy;
  276. return Ctx.DoubleTy;
  277. }
  278. if (CS.getKind() == ConversionSpecifier::nArg) {
  279. switch (LM.getKind()) {
  280. case LengthModifier::None:
  281. return ArgType::PtrTo(Ctx.IntTy);
  282. case LengthModifier::AsChar:
  283. return ArgType::PtrTo(Ctx.SignedCharTy);
  284. case LengthModifier::AsShort:
  285. return ArgType::PtrTo(Ctx.ShortTy);
  286. case LengthModifier::AsLong:
  287. return ArgType::PtrTo(Ctx.LongTy);
  288. case LengthModifier::AsLongLong:
  289. case LengthModifier::AsQuad:
  290. return ArgType::PtrTo(Ctx.LongLongTy);
  291. case LengthModifier::AsIntMax:
  292. return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
  293. case LengthModifier::AsSizeT:
  294. return ArgType(); // FIXME: ssize_t
  295. case LengthModifier::AsPtrDiff:
  296. return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
  297. case LengthModifier::AsLongDouble:
  298. return ArgType(); // FIXME: Is this a known extension?
  299. case LengthModifier::AsAllocate:
  300. case LengthModifier::AsMAllocate:
  301. return ArgType::Invalid();
  302. }
  303. }
  304. switch (CS.getKind()) {
  305. case ConversionSpecifier::sArg:
  306. if (LM.getKind() == LengthModifier::AsWideChar) {
  307. if (IsObjCLiteral)
  308. return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst());
  309. return ArgType(ArgType::WCStrTy, "wchar_t *");
  310. }
  311. return ArgType::CStrTy;
  312. case ConversionSpecifier::SArg:
  313. if (IsObjCLiteral)
  314. return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst());
  315. return ArgType(ArgType::WCStrTy, "wchar_t *");
  316. case ConversionSpecifier::CArg:
  317. if (IsObjCLiteral)
  318. return Ctx.UnsignedShortTy;
  319. return ArgType(Ctx.WCharTy, "wchar_t");
  320. case ConversionSpecifier::pArg:
  321. return ArgType::CPointerTy;
  322. case ConversionSpecifier::ObjCObjArg:
  323. return ArgType::ObjCPointerTy;
  324. default:
  325. break;
  326. }
  327. // FIXME: Handle other cases.
  328. return ArgType();
  329. }
  330. bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
  331. ASTContext &Ctx, bool IsObjCLiteral) {
  332. // %n is different from other conversion specifiers; don't try to fix it.
  333. if (CS.getKind() == ConversionSpecifier::nArg)
  334. return false;
  335. // Handle Objective-C objects first. Note that while the '%@' specifier will
  336. // not warn for structure pointer or void pointer arguments (because that's
  337. // how CoreFoundation objects are implemented), we only show a fixit for '%@'
  338. // if we know it's an object (block, id, class, or __attribute__((NSObject))).
  339. if (QT->isObjCRetainableType()) {
  340. if (!IsObjCLiteral)
  341. return false;
  342. CS.setKind(ConversionSpecifier::ObjCObjArg);
  343. // Disable irrelevant flags
  344. HasThousandsGrouping = false;
  345. HasPlusPrefix = false;
  346. HasSpacePrefix = false;
  347. HasAlternativeForm = false;
  348. HasLeadingZeroes = false;
  349. Precision.setHowSpecified(OptionalAmount::NotSpecified);
  350. LM.setKind(LengthModifier::None);
  351. return true;
  352. }
  353. // Handle strings next (char *, wchar_t *)
  354. if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
  355. CS.setKind(ConversionSpecifier::sArg);
  356. // Disable irrelevant flags
  357. HasAlternativeForm = 0;
  358. HasLeadingZeroes = 0;
  359. // Set the long length modifier for wide characters
  360. if (QT->getPointeeType()->isWideCharType())
  361. LM.setKind(LengthModifier::AsWideChar);
  362. else
  363. LM.setKind(LengthModifier::None);
  364. return true;
  365. }
  366. // If it's an enum, get its underlying type.
  367. if (const EnumType *ETy = QT->getAs<EnumType>())
  368. QT = ETy->getDecl()->getIntegerType();
  369. // We can only work with builtin types.
  370. const BuiltinType *BT = QT->getAs<BuiltinType>();
  371. if (!BT)
  372. return false;
  373. // Set length modifier
  374. switch (BT->getKind()) {
  375. case BuiltinType::Bool:
  376. case BuiltinType::WChar_U:
  377. case BuiltinType::WChar_S:
  378. case BuiltinType::Char16:
  379. case BuiltinType::Char32:
  380. case BuiltinType::UInt128:
  381. case BuiltinType::Int128:
  382. case BuiltinType::Half:
  383. // Various types which are non-trivial to correct.
  384. return false;
  385. #define SIGNED_TYPE(Id, SingletonId)
  386. #define UNSIGNED_TYPE(Id, SingletonId)
  387. #define FLOATING_TYPE(Id, SingletonId)
  388. #define BUILTIN_TYPE(Id, SingletonId) \
  389. case BuiltinType::Id:
  390. #include "clang/AST/BuiltinTypes.def"
  391. // Misc other stuff which doesn't make sense here.
  392. return false;
  393. case BuiltinType::UInt:
  394. case BuiltinType::Int:
  395. case BuiltinType::Float:
  396. case BuiltinType::Double:
  397. LM.setKind(LengthModifier::None);
  398. break;
  399. case BuiltinType::Char_U:
  400. case BuiltinType::UChar:
  401. case BuiltinType::Char_S:
  402. case BuiltinType::SChar:
  403. LM.setKind(LengthModifier::AsChar);
  404. break;
  405. case BuiltinType::Short:
  406. case BuiltinType::UShort:
  407. LM.setKind(LengthModifier::AsShort);
  408. break;
  409. case BuiltinType::Long:
  410. case BuiltinType::ULong:
  411. LM.setKind(LengthModifier::AsLong);
  412. break;
  413. case BuiltinType::LongLong:
  414. case BuiltinType::ULongLong:
  415. LM.setKind(LengthModifier::AsLongLong);
  416. break;
  417. case BuiltinType::LongDouble:
  418. LM.setKind(LengthModifier::AsLongDouble);
  419. break;
  420. }
  421. // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
  422. if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus0x))
  423. namedTypeToLengthModifier(QT, LM);
  424. // If fixing the length modifier was enough, we are done.
  425. if (hasValidLengthModifier(Ctx.getTargetInfo())) {
  426. const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
  427. if (ATR.isValid() && ATR.matchesType(Ctx, QT))
  428. return true;
  429. }
  430. // Set conversion specifier and disable any flags which do not apply to it.
  431. // Let typedefs to char fall through to int, as %c is silly for uint8_t.
  432. if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) {
  433. CS.setKind(ConversionSpecifier::cArg);
  434. LM.setKind(LengthModifier::None);
  435. Precision.setHowSpecified(OptionalAmount::NotSpecified);
  436. HasAlternativeForm = 0;
  437. HasLeadingZeroes = 0;
  438. HasPlusPrefix = 0;
  439. }
  440. // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
  441. else if (QT->isRealFloatingType()) {
  442. CS.setKind(ConversionSpecifier::fArg);
  443. }
  444. else if (QT->isSignedIntegerType()) {
  445. CS.setKind(ConversionSpecifier::dArg);
  446. HasAlternativeForm = 0;
  447. }
  448. else if (QT->isUnsignedIntegerType()) {
  449. CS.setKind(ConversionSpecifier::uArg);
  450. HasAlternativeForm = 0;
  451. HasPlusPrefix = 0;
  452. } else {
  453. llvm_unreachable("Unexpected type");
  454. }
  455. return true;
  456. }
  457. void PrintfSpecifier::toString(raw_ostream &os) const {
  458. // Whilst some features have no defined order, we are using the order
  459. // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
  460. os << "%";
  461. // Positional args
  462. if (usesPositionalArg()) {
  463. os << getPositionalArgIndex() << "$";
  464. }
  465. // Conversion flags
  466. if (IsLeftJustified) os << "-";
  467. if (HasPlusPrefix) os << "+";
  468. if (HasSpacePrefix) os << " ";
  469. if (HasAlternativeForm) os << "#";
  470. if (HasLeadingZeroes) os << "0";
  471. // Minimum field width
  472. FieldWidth.toString(os);
  473. // Precision
  474. Precision.toString(os);
  475. // Length modifier
  476. os << LM.toString();
  477. // Conversion specifier
  478. os << CS.toString();
  479. }
  480. bool PrintfSpecifier::hasValidPlusPrefix() const {
  481. if (!HasPlusPrefix)
  482. return true;
  483. // The plus prefix only makes sense for signed conversions
  484. switch (CS.getKind()) {
  485. case ConversionSpecifier::dArg:
  486. case ConversionSpecifier::iArg:
  487. case ConversionSpecifier::fArg:
  488. case ConversionSpecifier::FArg:
  489. case ConversionSpecifier::eArg:
  490. case ConversionSpecifier::EArg:
  491. case ConversionSpecifier::gArg:
  492. case ConversionSpecifier::GArg:
  493. case ConversionSpecifier::aArg:
  494. case ConversionSpecifier::AArg:
  495. return true;
  496. default:
  497. return false;
  498. }
  499. }
  500. bool PrintfSpecifier::hasValidAlternativeForm() const {
  501. if (!HasAlternativeForm)
  502. return true;
  503. // Alternate form flag only valid with the oxXaAeEfFgG conversions
  504. switch (CS.getKind()) {
  505. case ConversionSpecifier::oArg:
  506. case ConversionSpecifier::xArg:
  507. case ConversionSpecifier::XArg:
  508. case ConversionSpecifier::aArg:
  509. case ConversionSpecifier::AArg:
  510. case ConversionSpecifier::eArg:
  511. case ConversionSpecifier::EArg:
  512. case ConversionSpecifier::fArg:
  513. case ConversionSpecifier::FArg:
  514. case ConversionSpecifier::gArg:
  515. case ConversionSpecifier::GArg:
  516. return true;
  517. default:
  518. return false;
  519. }
  520. }
  521. bool PrintfSpecifier::hasValidLeadingZeros() const {
  522. if (!HasLeadingZeroes)
  523. return true;
  524. // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
  525. switch (CS.getKind()) {
  526. case ConversionSpecifier::dArg:
  527. case ConversionSpecifier::iArg:
  528. case ConversionSpecifier::oArg:
  529. case ConversionSpecifier::uArg:
  530. case ConversionSpecifier::xArg:
  531. case ConversionSpecifier::XArg:
  532. case ConversionSpecifier::aArg:
  533. case ConversionSpecifier::AArg:
  534. case ConversionSpecifier::eArg:
  535. case ConversionSpecifier::EArg:
  536. case ConversionSpecifier::fArg:
  537. case ConversionSpecifier::FArg:
  538. case ConversionSpecifier::gArg:
  539. case ConversionSpecifier::GArg:
  540. return true;
  541. default:
  542. return false;
  543. }
  544. }
  545. bool PrintfSpecifier::hasValidSpacePrefix() const {
  546. if (!HasSpacePrefix)
  547. return true;
  548. // The space prefix only makes sense for signed conversions
  549. switch (CS.getKind()) {
  550. case ConversionSpecifier::dArg:
  551. case ConversionSpecifier::iArg:
  552. case ConversionSpecifier::fArg:
  553. case ConversionSpecifier::FArg:
  554. case ConversionSpecifier::eArg:
  555. case ConversionSpecifier::EArg:
  556. case ConversionSpecifier::gArg:
  557. case ConversionSpecifier::GArg:
  558. case ConversionSpecifier::aArg:
  559. case ConversionSpecifier::AArg:
  560. return true;
  561. default:
  562. return false;
  563. }
  564. }
  565. bool PrintfSpecifier::hasValidLeftJustified() const {
  566. if (!IsLeftJustified)
  567. return true;
  568. // The left justified flag is valid for all conversions except n
  569. switch (CS.getKind()) {
  570. case ConversionSpecifier::nArg:
  571. return false;
  572. default:
  573. return true;
  574. }
  575. }
  576. bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
  577. if (!HasThousandsGrouping)
  578. return true;
  579. switch (CS.getKind()) {
  580. case ConversionSpecifier::dArg:
  581. case ConversionSpecifier::iArg:
  582. case ConversionSpecifier::uArg:
  583. case ConversionSpecifier::fArg:
  584. case ConversionSpecifier::FArg:
  585. case ConversionSpecifier::gArg:
  586. case ConversionSpecifier::GArg:
  587. return true;
  588. default:
  589. return false;
  590. }
  591. }
  592. bool PrintfSpecifier::hasValidPrecision() const {
  593. if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
  594. return true;
  595. // Precision is only valid with the diouxXaAeEfFgGs conversions
  596. switch (CS.getKind()) {
  597. case ConversionSpecifier::dArg:
  598. case ConversionSpecifier::iArg:
  599. case ConversionSpecifier::oArg:
  600. case ConversionSpecifier::uArg:
  601. case ConversionSpecifier::xArg:
  602. case ConversionSpecifier::XArg:
  603. case ConversionSpecifier::aArg:
  604. case ConversionSpecifier::AArg:
  605. case ConversionSpecifier::eArg:
  606. case ConversionSpecifier::EArg:
  607. case ConversionSpecifier::fArg:
  608. case ConversionSpecifier::FArg:
  609. case ConversionSpecifier::gArg:
  610. case ConversionSpecifier::GArg:
  611. case ConversionSpecifier::sArg:
  612. return true;
  613. default:
  614. return false;
  615. }
  616. }
  617. bool PrintfSpecifier::hasValidFieldWidth() const {
  618. if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
  619. return true;
  620. // The field width is valid for all conversions except n
  621. switch (CS.getKind()) {
  622. case ConversionSpecifier::nArg:
  623. return false;
  624. default:
  625. return true;
  626. }
  627. }