PrintfFormatString.cpp 20 KB

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