PrintfFormatString.cpp revision cdbe1e0d85d7d32452dd1c52758d7bfaa1c0663b
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 ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
363                         "const unichar *");
364        return ArgType(ArgType::WCStrTy, "wchar_t *");
365      }
366      return ArgType::CStrTy;
367    case ConversionSpecifier::SArg:
368      if (IsObjCLiteral)
369        return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
370                       "const unichar *");
371      return ArgType(ArgType::WCStrTy, "wchar_t *");
372    case ConversionSpecifier::CArg:
373      if (IsObjCLiteral)
374        return ArgType(Ctx.UnsignedShortTy, "unichar");
375      return ArgType(Ctx.WCharTy, "wchar_t");
376    case ConversionSpecifier::pArg:
377      return ArgType::CPointerTy;
378    case ConversionSpecifier::ObjCObjArg:
379      return ArgType::ObjCPointerTy;
380    default:
381      break;
382  }
383
384  // FIXME: Handle other cases.
385  return ArgType();
386}
387
388bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
389                              ASTContext &Ctx, bool IsObjCLiteral) {
390  // %n is different from other conversion specifiers; don't try to fix it.
391  if (CS.getKind() == ConversionSpecifier::nArg)
392    return false;
393
394  // Handle Objective-C objects first. Note that while the '%@' specifier will
395  // not warn for structure pointer or void pointer arguments (because that's
396  // how CoreFoundation objects are implemented), we only show a fixit for '%@'
397  // if we know it's an object (block, id, class, or __attribute__((NSObject))).
398  if (QT->isObjCRetainableType()) {
399    if (!IsObjCLiteral)
400      return false;
401
402    CS.setKind(ConversionSpecifier::ObjCObjArg);
403
404    // Disable irrelevant flags
405    HasThousandsGrouping = false;
406    HasPlusPrefix = false;
407    HasSpacePrefix = false;
408    HasAlternativeForm = false;
409    HasLeadingZeroes = false;
410    Precision.setHowSpecified(OptionalAmount::NotSpecified);
411    LM.setKind(LengthModifier::None);
412
413    return true;
414  }
415
416  // Handle strings next (char *, wchar_t *)
417  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
418    CS.setKind(ConversionSpecifier::sArg);
419
420    // Disable irrelevant flags
421    HasAlternativeForm = 0;
422    HasLeadingZeroes = 0;
423
424    // Set the long length modifier for wide characters
425    if (QT->getPointeeType()->isWideCharType())
426      LM.setKind(LengthModifier::AsWideChar);
427    else
428      LM.setKind(LengthModifier::None);
429
430    return true;
431  }
432
433  // If it's an enum, get its underlying type.
434  if (const EnumType *ETy = QT->getAs<EnumType>())
435    QT = ETy->getDecl()->getIntegerType();
436
437  // We can only work with builtin types.
438  const BuiltinType *BT = QT->getAs<BuiltinType>();
439  if (!BT)
440    return false;
441
442  // Set length modifier
443  switch (BT->getKind()) {
444  case BuiltinType::Bool:
445  case BuiltinType::WChar_U:
446  case BuiltinType::WChar_S:
447  case BuiltinType::Char16:
448  case BuiltinType::Char32:
449  case BuiltinType::UInt128:
450  case BuiltinType::Int128:
451  case BuiltinType::Half:
452    // Various types which are non-trivial to correct.
453    return false;
454
455#define SIGNED_TYPE(Id, SingletonId)
456#define UNSIGNED_TYPE(Id, SingletonId)
457#define FLOATING_TYPE(Id, SingletonId)
458#define BUILTIN_TYPE(Id, SingletonId) \
459  case BuiltinType::Id:
460#include "clang/AST/BuiltinTypes.def"
461    // Misc other stuff which doesn't make sense here.
462    return false;
463
464  case BuiltinType::UInt:
465  case BuiltinType::Int:
466  case BuiltinType::Float:
467  case BuiltinType::Double:
468    LM.setKind(LengthModifier::None);
469    break;
470
471  case BuiltinType::Char_U:
472  case BuiltinType::UChar:
473  case BuiltinType::Char_S:
474  case BuiltinType::SChar:
475    LM.setKind(LengthModifier::AsChar);
476    break;
477
478  case BuiltinType::Short:
479  case BuiltinType::UShort:
480    LM.setKind(LengthModifier::AsShort);
481    break;
482
483  case BuiltinType::Long:
484  case BuiltinType::ULong:
485    LM.setKind(LengthModifier::AsLong);
486    break;
487
488  case BuiltinType::LongLong:
489  case BuiltinType::ULongLong:
490    LM.setKind(LengthModifier::AsLongLong);
491    break;
492
493  case BuiltinType::LongDouble:
494    LM.setKind(LengthModifier::AsLongDouble);
495    break;
496  }
497
498  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
499  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
500    namedTypeToLengthModifier(QT, LM);
501
502  // If fixing the length modifier was enough, we might be done.
503  if (hasValidLengthModifier(Ctx.getTargetInfo())) {
504    // If we're going to offer a fix anyway, make sure the sign matches.
505    switch (CS.getKind()) {
506    case ConversionSpecifier::uArg:
507    case ConversionSpecifier::UArg:
508      if (QT->isSignedIntegerType())
509        CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
510      break;
511    case ConversionSpecifier::dArg:
512    case ConversionSpecifier::DArg:
513    case ConversionSpecifier::iArg:
514      if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
515        CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
516      break;
517    default:
518      // Other specifiers do not have signed/unsigned variants.
519      break;
520    }
521
522    const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
523    if (ATR.isValid() && ATR.matchesType(Ctx, QT))
524      return true;
525  }
526
527  // Set conversion specifier and disable any flags which do not apply to it.
528  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
529  if (!isa<TypedefType>(QT) && QT->isCharType()) {
530    CS.setKind(ConversionSpecifier::cArg);
531    LM.setKind(LengthModifier::None);
532    Precision.setHowSpecified(OptionalAmount::NotSpecified);
533    HasAlternativeForm = 0;
534    HasLeadingZeroes = 0;
535    HasPlusPrefix = 0;
536  }
537  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
538  else if (QT->isRealFloatingType()) {
539    CS.setKind(ConversionSpecifier::fArg);
540  }
541  else if (QT->isSignedIntegerType()) {
542    CS.setKind(ConversionSpecifier::dArg);
543    HasAlternativeForm = 0;
544  }
545  else if (QT->isUnsignedIntegerType()) {
546    CS.setKind(ConversionSpecifier::uArg);
547    HasAlternativeForm = 0;
548    HasPlusPrefix = 0;
549  } else {
550    llvm_unreachable("Unexpected type");
551  }
552
553  return true;
554}
555
556void PrintfSpecifier::toString(raw_ostream &os) const {
557  // Whilst some features have no defined order, we are using the order
558  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
559  os << "%";
560
561  // Positional args
562  if (usesPositionalArg()) {
563    os << getPositionalArgIndex() << "$";
564  }
565
566  // Conversion flags
567  if (IsLeftJustified)    os << "-";
568  if (HasPlusPrefix)      os << "+";
569  if (HasSpacePrefix)     os << " ";
570  if (HasAlternativeForm) os << "#";
571  if (HasLeadingZeroes)   os << "0";
572
573  // Minimum field width
574  FieldWidth.toString(os);
575  // Precision
576  Precision.toString(os);
577  // Length modifier
578  os << LM.toString();
579  // Conversion specifier
580  os << CS.toString();
581}
582
583bool PrintfSpecifier::hasValidPlusPrefix() const {
584  if (!HasPlusPrefix)
585    return true;
586
587  // The plus prefix only makes sense for signed conversions
588  switch (CS.getKind()) {
589  case ConversionSpecifier::dArg:
590  case ConversionSpecifier::DArg:
591  case ConversionSpecifier::iArg:
592  case ConversionSpecifier::fArg:
593  case ConversionSpecifier::FArg:
594  case ConversionSpecifier::eArg:
595  case ConversionSpecifier::EArg:
596  case ConversionSpecifier::gArg:
597  case ConversionSpecifier::GArg:
598  case ConversionSpecifier::aArg:
599  case ConversionSpecifier::AArg:
600    return true;
601
602  default:
603    return false;
604  }
605}
606
607bool PrintfSpecifier::hasValidAlternativeForm() const {
608  if (!HasAlternativeForm)
609    return true;
610
611  // Alternate form flag only valid with the oxXaAeEfFgG conversions
612  switch (CS.getKind()) {
613  case ConversionSpecifier::oArg:
614  case ConversionSpecifier::OArg:
615  case ConversionSpecifier::xArg:
616  case ConversionSpecifier::XArg:
617  case ConversionSpecifier::aArg:
618  case ConversionSpecifier::AArg:
619  case ConversionSpecifier::eArg:
620  case ConversionSpecifier::EArg:
621  case ConversionSpecifier::fArg:
622  case ConversionSpecifier::FArg:
623  case ConversionSpecifier::gArg:
624  case ConversionSpecifier::GArg:
625    return true;
626
627  default:
628    return false;
629  }
630}
631
632bool PrintfSpecifier::hasValidLeadingZeros() const {
633  if (!HasLeadingZeroes)
634    return true;
635
636  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
637  switch (CS.getKind()) {
638  case ConversionSpecifier::dArg:
639  case ConversionSpecifier::DArg:
640  case ConversionSpecifier::iArg:
641  case ConversionSpecifier::oArg:
642  case ConversionSpecifier::OArg:
643  case ConversionSpecifier::uArg:
644  case ConversionSpecifier::UArg:
645  case ConversionSpecifier::xArg:
646  case ConversionSpecifier::XArg:
647  case ConversionSpecifier::aArg:
648  case ConversionSpecifier::AArg:
649  case ConversionSpecifier::eArg:
650  case ConversionSpecifier::EArg:
651  case ConversionSpecifier::fArg:
652  case ConversionSpecifier::FArg:
653  case ConversionSpecifier::gArg:
654  case ConversionSpecifier::GArg:
655    return true;
656
657  default:
658    return false;
659  }
660}
661
662bool PrintfSpecifier::hasValidSpacePrefix() const {
663  if (!HasSpacePrefix)
664    return true;
665
666  // The space prefix only makes sense for signed conversions
667  switch (CS.getKind()) {
668  case ConversionSpecifier::dArg:
669  case ConversionSpecifier::DArg:
670  case ConversionSpecifier::iArg:
671  case ConversionSpecifier::fArg:
672  case ConversionSpecifier::FArg:
673  case ConversionSpecifier::eArg:
674  case ConversionSpecifier::EArg:
675  case ConversionSpecifier::gArg:
676  case ConversionSpecifier::GArg:
677  case ConversionSpecifier::aArg:
678  case ConversionSpecifier::AArg:
679    return true;
680
681  default:
682    return false;
683  }
684}
685
686bool PrintfSpecifier::hasValidLeftJustified() const {
687  if (!IsLeftJustified)
688    return true;
689
690  // The left justified flag is valid for all conversions except n
691  switch (CS.getKind()) {
692  case ConversionSpecifier::nArg:
693    return false;
694
695  default:
696    return true;
697  }
698}
699
700bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
701  if (!HasThousandsGrouping)
702    return true;
703
704  switch (CS.getKind()) {
705    case ConversionSpecifier::dArg:
706    case ConversionSpecifier::DArg:
707    case ConversionSpecifier::iArg:
708    case ConversionSpecifier::uArg:
709    case ConversionSpecifier::UArg:
710    case ConversionSpecifier::fArg:
711    case ConversionSpecifier::FArg:
712    case ConversionSpecifier::gArg:
713    case ConversionSpecifier::GArg:
714      return true;
715    default:
716      return false;
717  }
718}
719
720bool PrintfSpecifier::hasValidPrecision() const {
721  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
722    return true;
723
724  // Precision is only valid with the diouxXaAeEfFgGs conversions
725  switch (CS.getKind()) {
726  case ConversionSpecifier::dArg:
727  case ConversionSpecifier::DArg:
728  case ConversionSpecifier::iArg:
729  case ConversionSpecifier::oArg:
730  case ConversionSpecifier::OArg:
731  case ConversionSpecifier::uArg:
732  case ConversionSpecifier::UArg:
733  case ConversionSpecifier::xArg:
734  case ConversionSpecifier::XArg:
735  case ConversionSpecifier::aArg:
736  case ConversionSpecifier::AArg:
737  case ConversionSpecifier::eArg:
738  case ConversionSpecifier::EArg:
739  case ConversionSpecifier::fArg:
740  case ConversionSpecifier::FArg:
741  case ConversionSpecifier::gArg:
742  case ConversionSpecifier::GArg:
743  case ConversionSpecifier::sArg:
744    return true;
745
746  default:
747    return false;
748  }
749}
750bool PrintfSpecifier::hasValidFieldWidth() const {
751  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
752      return true;
753
754  // The field width is valid for all conversions except n
755  switch (CS.getKind()) {
756  case ConversionSpecifier::nArg:
757    return false;
758
759  default:
760    return true;
761  }
762}
763