PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/llvm/tools/clang/lib/Analysis/PrintfFormatString.cpp

https://bitbucket.org/freebsd/freebsd-head
C++ | 679 lines | 516 code | 81 blank | 82 comment | 131 complexity | 652810c10f794128360fcbd41bb251be MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, BSD-3-Clause, JSON, LGPL-2.1, GPL-2.0, LGPL-2.0, AGPL-1.0, BSD-2-Clause, 0BSD
  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::ArgTypeResult;
  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. // FreeBSD format extensions
  175. case 'b': if (LO.FormatExtensions) k = ConversionSpecifier::bArg; break; /* check for int and then char * */
  176. case 'r': if (LO.FormatExtensions) k = ConversionSpecifier::rArg; break;
  177. case 'y': if (LO.FormatExtensions) k = ConversionSpecifier::iArg; break;
  178. case 'D': if (LO.FormatExtensions) k = ConversionSpecifier::DArg; break; /* check for u_char * pointer and a char * string */
  179. }
  180. PrintfConversionSpecifier CS(conversionPosition, k);
  181. FS.setConversionSpecifier(CS);
  182. if (CS.consumesDataArgument() && !FS.usesPositionalArg())
  183. FS.setArgIndex(argIndex++);
  184. // FreeBSD extension
  185. if (k == ConversionSpecifier::bArg || k == ConversionSpecifier::DArg)
  186. argIndex++;
  187. if (k == ConversionSpecifier::InvalidSpecifier) {
  188. // Assume the conversion takes one argument.
  189. return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
  190. }
  191. return PrintfSpecifierResult(Start, FS);
  192. }
  193. bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
  194. const char *I,
  195. const char *E,
  196. const LangOptions &LO) {
  197. unsigned argIndex = 0;
  198. // Keep looking for a format specifier until we have exhausted the string.
  199. while (I != E) {
  200. const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
  201. LO);
  202. // Did a fail-stop error of any kind occur when parsing the specifier?
  203. // If so, don't do any more processing.
  204. if (FSR.shouldStop())
  205. return true;;
  206. // Did we exhaust the string or encounter an error that
  207. // we can recover from?
  208. if (!FSR.hasValue())
  209. continue;
  210. // We have a format specifier. Pass it to the callback.
  211. if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
  212. I - FSR.getStart()))
  213. return true;
  214. }
  215. assert(I == E && "Format string not exhausted");
  216. return false;
  217. }
  218. //===----------------------------------------------------------------------===//
  219. // Methods on PrintfSpecifier.
  220. //===----------------------------------------------------------------------===//
  221. ArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx,
  222. bool IsObjCLiteral) const {
  223. const PrintfConversionSpecifier &CS = getConversionSpecifier();
  224. if (!CS.consumesDataArgument())
  225. return ArgTypeResult::Invalid();
  226. if (CS.getKind() == ConversionSpecifier::cArg)
  227. switch (LM.getKind()) {
  228. case LengthModifier::None: return Ctx.IntTy;
  229. case LengthModifier::AsLong:
  230. return ArgTypeResult(ArgTypeResult::WIntTy, "wint_t");
  231. default:
  232. return ArgTypeResult::Invalid();
  233. }
  234. if (CS.isIntArg())
  235. switch (LM.getKind()) {
  236. case LengthModifier::AsLongDouble:
  237. // GNU extension.
  238. return Ctx.LongLongTy;
  239. case LengthModifier::None: return Ctx.IntTy;
  240. case LengthModifier::AsChar: return ArgTypeResult::AnyCharTy;
  241. case LengthModifier::AsShort: return Ctx.ShortTy;
  242. case LengthModifier::AsLong: return Ctx.LongTy;
  243. case LengthModifier::AsLongLong:
  244. case LengthModifier::AsQuad:
  245. return Ctx.LongLongTy;
  246. case LengthModifier::AsIntMax:
  247. return ArgTypeResult(Ctx.getIntMaxType(), "intmax_t");
  248. case LengthModifier::AsSizeT:
  249. // FIXME: How to get the corresponding signed version of size_t?
  250. return ArgTypeResult();
  251. case LengthModifier::AsPtrDiff:
  252. return ArgTypeResult(Ctx.getPointerDiffType(), "ptrdiff_t");
  253. case LengthModifier::AsAllocate:
  254. case LengthModifier::AsMAllocate:
  255. return ArgTypeResult::Invalid();
  256. }
  257. if (CS.isUIntArg())
  258. switch (LM.getKind()) {
  259. case LengthModifier::AsLongDouble:
  260. // GNU extension.
  261. return Ctx.UnsignedLongLongTy;
  262. case LengthModifier::None: return Ctx.UnsignedIntTy;
  263. case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
  264. case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
  265. case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
  266. case LengthModifier::AsLongLong:
  267. case LengthModifier::AsQuad:
  268. return Ctx.UnsignedLongLongTy;
  269. case LengthModifier::AsIntMax:
  270. return ArgTypeResult(Ctx.getUIntMaxType(), "uintmax_t");
  271. case LengthModifier::AsSizeT:
  272. return ArgTypeResult(Ctx.getSizeType(), "size_t");
  273. case LengthModifier::AsPtrDiff:
  274. // FIXME: How to get the corresponding unsigned
  275. // version of ptrdiff_t?
  276. return ArgTypeResult();
  277. case LengthModifier::AsAllocate:
  278. case LengthModifier::AsMAllocate:
  279. return ArgTypeResult::Invalid();
  280. }
  281. if (CS.isDoubleArg()) {
  282. if (LM.getKind() == LengthModifier::AsLongDouble)
  283. return Ctx.LongDoubleTy;
  284. return Ctx.DoubleTy;
  285. }
  286. switch (CS.getKind()) {
  287. case ConversionSpecifier::sArg:
  288. if (LM.getKind() == LengthModifier::AsWideChar) {
  289. if (IsObjCLiteral)
  290. return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst());
  291. return ArgTypeResult(ArgTypeResult::WCStrTy, "wchar_t *");
  292. }
  293. return ArgTypeResult::CStrTy;
  294. case ConversionSpecifier::SArg:
  295. if (IsObjCLiteral)
  296. return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst());
  297. return ArgTypeResult(ArgTypeResult::WCStrTy, "wchar_t *");
  298. case ConversionSpecifier::CArg:
  299. if (IsObjCLiteral)
  300. return Ctx.UnsignedShortTy;
  301. return ArgTypeResult(Ctx.WCharTy, "wchar_t");
  302. case ConversionSpecifier::pArg:
  303. return ArgTypeResult::CPointerTy;
  304. case ConversionSpecifier::ObjCObjArg:
  305. return ArgTypeResult::ObjCPointerTy;
  306. default:
  307. break;
  308. }
  309. // FIXME: Handle other cases.
  310. return ArgTypeResult();
  311. }
  312. bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
  313. ASTContext &Ctx, bool IsObjCLiteral) {
  314. // Handle strings first (char *, wchar_t *)
  315. if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
  316. CS.setKind(ConversionSpecifier::sArg);
  317. // Disable irrelevant flags
  318. HasAlternativeForm = 0;
  319. HasLeadingZeroes = 0;
  320. // Set the long length modifier for wide characters
  321. if (QT->getPointeeType()->isWideCharType())
  322. LM.setKind(LengthModifier::AsWideChar);
  323. else
  324. LM.setKind(LengthModifier::None);
  325. return true;
  326. }
  327. // We can only work with builtin types.
  328. const BuiltinType *BT = QT->getAs<BuiltinType>();
  329. if (!BT)
  330. return false;
  331. // Set length modifier
  332. switch (BT->getKind()) {
  333. case BuiltinType::Bool:
  334. case BuiltinType::WChar_U:
  335. case BuiltinType::WChar_S:
  336. case BuiltinType::Char16:
  337. case BuiltinType::Char32:
  338. case BuiltinType::UInt128:
  339. case BuiltinType::Int128:
  340. case BuiltinType::Half:
  341. // Various types which are non-trivial to correct.
  342. return false;
  343. #define SIGNED_TYPE(Id, SingletonId)
  344. #define UNSIGNED_TYPE(Id, SingletonId)
  345. #define FLOATING_TYPE(Id, SingletonId)
  346. #define BUILTIN_TYPE(Id, SingletonId) \
  347. case BuiltinType::Id:
  348. #include "clang/AST/BuiltinTypes.def"
  349. // Misc other stuff which doesn't make sense here.
  350. return false;
  351. case BuiltinType::UInt:
  352. case BuiltinType::Int:
  353. case BuiltinType::Float:
  354. case BuiltinType::Double:
  355. LM.setKind(LengthModifier::None);
  356. break;
  357. case BuiltinType::Char_U:
  358. case BuiltinType::UChar:
  359. case BuiltinType::Char_S:
  360. case BuiltinType::SChar:
  361. LM.setKind(LengthModifier::AsChar);
  362. break;
  363. case BuiltinType::Short:
  364. case BuiltinType::UShort:
  365. LM.setKind(LengthModifier::AsShort);
  366. break;
  367. case BuiltinType::Long:
  368. case BuiltinType::ULong:
  369. LM.setKind(LengthModifier::AsLong);
  370. break;
  371. case BuiltinType::LongLong:
  372. case BuiltinType::ULongLong:
  373. LM.setKind(LengthModifier::AsLongLong);
  374. break;
  375. case BuiltinType::LongDouble:
  376. LM.setKind(LengthModifier::AsLongDouble);
  377. break;
  378. }
  379. // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
  380. if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) {
  381. const IdentifierInfo *Identifier = QT.getBaseTypeIdentifier();
  382. if (Identifier->getName() == "size_t") {
  383. LM.setKind(LengthModifier::AsSizeT);
  384. } else if (Identifier->getName() == "ssize_t") {
  385. // Not C99, but common in Unix.
  386. LM.setKind(LengthModifier::AsSizeT);
  387. } else if (Identifier->getName() == "intmax_t") {
  388. LM.setKind(LengthModifier::AsIntMax);
  389. } else if (Identifier->getName() == "uintmax_t") {
  390. LM.setKind(LengthModifier::AsIntMax);
  391. } else if (Identifier->getName() == "ptrdiff_t") {
  392. LM.setKind(LengthModifier::AsPtrDiff);
  393. }
  394. }
  395. // If fixing the length modifier was enough, we are done.
  396. const analyze_printf::ArgTypeResult &ATR = getArgType(Ctx, IsObjCLiteral);
  397. if (hasValidLengthModifier() && ATR.isValid() && ATR.matchesType(Ctx, QT))
  398. return true;
  399. // Set conversion specifier and disable any flags which do not apply to it.
  400. // Let typedefs to char fall through to int, as %c is silly for uint8_t.
  401. if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) {
  402. CS.setKind(ConversionSpecifier::cArg);
  403. LM.setKind(LengthModifier::None);
  404. Precision.setHowSpecified(OptionalAmount::NotSpecified);
  405. HasAlternativeForm = 0;
  406. HasLeadingZeroes = 0;
  407. HasPlusPrefix = 0;
  408. }
  409. // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
  410. else if (QT->isRealFloatingType()) {
  411. CS.setKind(ConversionSpecifier::fArg);
  412. }
  413. else if (QT->isSignedIntegerType()) {
  414. CS.setKind(ConversionSpecifier::dArg);
  415. HasAlternativeForm = 0;
  416. }
  417. else if (QT->isUnsignedIntegerType()) {
  418. CS.setKind(ConversionSpecifier::uArg);
  419. HasAlternativeForm = 0;
  420. HasPlusPrefix = 0;
  421. } else {
  422. llvm_unreachable("Unexpected type");
  423. }
  424. return true;
  425. }
  426. void PrintfSpecifier::toString(raw_ostream &os) const {
  427. // Whilst some features have no defined order, we are using the order
  428. // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
  429. os << "%";
  430. // Positional args
  431. if (usesPositionalArg()) {
  432. os << getPositionalArgIndex() << "$";
  433. }
  434. // Conversion flags
  435. if (IsLeftJustified) os << "-";
  436. if (HasPlusPrefix) os << "+";
  437. if (HasSpacePrefix) os << " ";
  438. if (HasAlternativeForm) os << "#";
  439. if (HasLeadingZeroes) os << "0";
  440. // Minimum field width
  441. FieldWidth.toString(os);
  442. // Precision
  443. Precision.toString(os);
  444. // Length modifier
  445. os << LM.toString();
  446. // Conversion specifier
  447. os << CS.toString();
  448. }
  449. bool PrintfSpecifier::hasValidPlusPrefix() const {
  450. if (!HasPlusPrefix)
  451. return true;
  452. // The plus prefix only makes sense for signed conversions
  453. switch (CS.getKind()) {
  454. case ConversionSpecifier::dArg:
  455. case ConversionSpecifier::iArg:
  456. case ConversionSpecifier::fArg:
  457. case ConversionSpecifier::FArg:
  458. case ConversionSpecifier::eArg:
  459. case ConversionSpecifier::EArg:
  460. case ConversionSpecifier::gArg:
  461. case ConversionSpecifier::GArg:
  462. case ConversionSpecifier::aArg:
  463. case ConversionSpecifier::AArg:
  464. case ConversionSpecifier::rArg:
  465. return true;
  466. default:
  467. return false;
  468. }
  469. }
  470. bool PrintfSpecifier::hasValidAlternativeForm() const {
  471. if (!HasAlternativeForm)
  472. return true;
  473. // Alternate form flag only valid with the oxXaAeEfFgG conversions
  474. switch (CS.getKind()) {
  475. case ConversionSpecifier::oArg:
  476. case ConversionSpecifier::xArg:
  477. case ConversionSpecifier::XArg:
  478. case ConversionSpecifier::aArg:
  479. case ConversionSpecifier::AArg:
  480. case ConversionSpecifier::eArg:
  481. case ConversionSpecifier::EArg:
  482. case ConversionSpecifier::fArg:
  483. case ConversionSpecifier::FArg:
  484. case ConversionSpecifier::gArg:
  485. case ConversionSpecifier::GArg:
  486. case ConversionSpecifier::rArg:
  487. return true;
  488. default:
  489. return false;
  490. }
  491. }
  492. bool PrintfSpecifier::hasValidLeadingZeros() const {
  493. if (!HasLeadingZeroes)
  494. return true;
  495. // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
  496. switch (CS.getKind()) {
  497. case ConversionSpecifier::dArg:
  498. case ConversionSpecifier::iArg:
  499. case ConversionSpecifier::oArg:
  500. case ConversionSpecifier::uArg:
  501. case ConversionSpecifier::xArg:
  502. case ConversionSpecifier::XArg:
  503. case ConversionSpecifier::aArg:
  504. case ConversionSpecifier::AArg:
  505. case ConversionSpecifier::eArg:
  506. case ConversionSpecifier::EArg:
  507. case ConversionSpecifier::fArg:
  508. case ConversionSpecifier::FArg:
  509. case ConversionSpecifier::gArg:
  510. case ConversionSpecifier::GArg:
  511. return true;
  512. default:
  513. return false;
  514. }
  515. }
  516. bool PrintfSpecifier::hasValidSpacePrefix() const {
  517. if (!HasSpacePrefix)
  518. return true;
  519. // The space prefix only makes sense for signed conversions
  520. switch (CS.getKind()) {
  521. case ConversionSpecifier::dArg:
  522. case ConversionSpecifier::iArg:
  523. case ConversionSpecifier::fArg:
  524. case ConversionSpecifier::FArg:
  525. case ConversionSpecifier::eArg:
  526. case ConversionSpecifier::EArg:
  527. case ConversionSpecifier::gArg:
  528. case ConversionSpecifier::GArg:
  529. case ConversionSpecifier::aArg:
  530. case ConversionSpecifier::AArg:
  531. return true;
  532. default:
  533. return false;
  534. }
  535. }
  536. bool PrintfSpecifier::hasValidLeftJustified() const {
  537. if (!IsLeftJustified)
  538. return true;
  539. // The left justified flag is valid for all conversions except n
  540. switch (CS.getKind()) {
  541. case ConversionSpecifier::nArg:
  542. return false;
  543. default:
  544. return true;
  545. }
  546. }
  547. bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
  548. if (!HasThousandsGrouping)
  549. return true;
  550. switch (CS.getKind()) {
  551. case ConversionSpecifier::dArg:
  552. case ConversionSpecifier::iArg:
  553. case ConversionSpecifier::uArg:
  554. case ConversionSpecifier::fArg:
  555. case ConversionSpecifier::FArg:
  556. case ConversionSpecifier::gArg:
  557. case ConversionSpecifier::GArg:
  558. return true;
  559. default:
  560. return false;
  561. }
  562. }
  563. bool PrintfSpecifier::hasValidPrecision() const {
  564. if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
  565. return true;
  566. // Precision is only valid with the diouxXaAeEfFgGs conversions
  567. switch (CS.getKind()) {
  568. case ConversionSpecifier::dArg:
  569. case ConversionSpecifier::iArg:
  570. case ConversionSpecifier::oArg:
  571. case ConversionSpecifier::uArg:
  572. case ConversionSpecifier::xArg:
  573. case ConversionSpecifier::XArg:
  574. case ConversionSpecifier::aArg:
  575. case ConversionSpecifier::AArg:
  576. case ConversionSpecifier::eArg:
  577. case ConversionSpecifier::EArg:
  578. case ConversionSpecifier::fArg:
  579. case ConversionSpecifier::FArg:
  580. case ConversionSpecifier::gArg:
  581. case ConversionSpecifier::GArg:
  582. case ConversionSpecifier::sArg:
  583. return true;
  584. default:
  585. return false;
  586. }
  587. }
  588. bool PrintfSpecifier::hasValidFieldWidth() const {
  589. if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
  590. return true;
  591. // The field width is valid for all conversions except n
  592. switch (CS.getKind()) {
  593. case ConversionSpecifier::nArg:
  594. return false;
  595. default:
  596. return true;
  597. }
  598. }