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