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