PrintfFormatString.cpp revision 0c293ea13d452c1a47a05ada5a5ee9acc69c66cc
1//= PrintfFormatStrings.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/PrintfFormatString.h"
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/Type.h"
18#include "llvm/Support/raw_ostream.h"
19
20using clang::analyze_printf::ArgTypeResult;
21using clang::analyze_printf::FormatSpecifier;
22using clang::analyze_printf::FormatStringHandler;
23using clang::analyze_printf::OptionalAmount;
24using clang::analyze_printf::PositionContext;
25using clang::analyze_printf::ConversionSpecifier;
26using clang::analyze_printf::LengthModifier;
27
28using namespace clang;
29
30namespace {
31class FormatSpecifierResult {
32  FormatSpecifier FS;
33  const char *Start;
34  bool Stop;
35public:
36  FormatSpecifierResult(bool stop = false)
37    : Start(0), Stop(stop) {}
38  FormatSpecifierResult(const char *start,
39                        const FormatSpecifier &fs)
40    : FS(fs), Start(start), Stop(false) {}
41
42  const char *getStart() const { return Start; }
43  bool shouldStop() const { return Stop; }
44  bool hasValue() const { return Start != 0; }
45  const FormatSpecifier &getValue() const {
46    assert(hasValue());
47    return FS;
48  }
49  const FormatSpecifier &getValue() { return FS; }
50};
51} // end anonymous namespace
52
53template <typename T>
54class UpdateOnReturn {
55  T &ValueToUpdate;
56  const T &ValueToCopy;
57public:
58  UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)
59    : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}
60
61  ~UpdateOnReturn() {
62    ValueToUpdate = ValueToCopy;
63  }
64};
65
66//===----------------------------------------------------------------------===//
67// Methods for parsing format strings.
68//===----------------------------------------------------------------------===//
69
70static OptionalAmount ParseAmount(const char *&Beg, const char *E) {
71  const char *I = Beg;
72  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
73
74  unsigned accumulator = 0;
75  bool hasDigits = false;
76
77  for ( ; I != E; ++I) {
78    char c = *I;
79    if (c >= '0' && c <= '9') {
80      hasDigits = true;
81      accumulator = (accumulator * 10) + (c - '0');
82      continue;
83    }
84
85    if (hasDigits)
86      return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
87          false);
88
89    break;
90  }
91
92  return OptionalAmount();
93}
94
95static OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E,
96                                             unsigned &argIndex) {
97  if (*Beg == '*') {
98    ++Beg;
99    return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
100  }
101
102  return ParseAmount(Beg, E);
103}
104
105static OptionalAmount ParsePositionAmount(FormatStringHandler &H,
106                                          const char *Start,
107                                          const char *&Beg, const char *E,
108                                          PositionContext p) {
109  if (*Beg == '*') {
110    const char *I = Beg + 1;
111    const OptionalAmount &Amt = ParseAmount(I, E);
112
113    if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
114      H.HandleInvalidPosition(Beg, I - Beg, p);
115      return OptionalAmount(false);
116    }
117
118    if (I== E) {
119      // No more characters left?
120      H.HandleIncompleteFormatSpecifier(Start, E - Start);
121      return OptionalAmount(false);
122    }
123
124    assert(Amt.getHowSpecified() == OptionalAmount::Constant);
125
126    if (*I == '$') {
127      // Handle positional arguments
128
129      // Special case: '*0$', since this is an easy mistake.
130      if (Amt.getConstantAmount() == 0) {
131        H.HandleZeroPosition(Beg, I - Beg + 1);
132        return OptionalAmount(false);
133      }
134
135      const char *Tmp = Beg;
136      Beg = ++I;
137
138      return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
139                            Tmp, 0, true);
140    }
141
142    H.HandleInvalidPosition(Beg, I - Beg, p);
143    return OptionalAmount(false);
144  }
145
146  return ParseAmount(Beg, E);
147}
148
149static bool ParsePrecision(FormatStringHandler &H, FormatSpecifier &FS,
150                           const char *Start, const char *&Beg, const char *E,
151                           unsigned *argIndex) {
152  if (argIndex) {
153    FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
154  }
155  else {
156    const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
157                                                  analyze_printf::PrecisionPos);
158    if (Amt.isInvalid())
159      return true;
160    FS.setPrecision(Amt);
161  }
162  return false;
163}
164
165static bool ParseFieldWidth(FormatStringHandler &H, FormatSpecifier &FS,
166                            const char *Start, const char *&Beg, const char *E,
167                            unsigned *argIndex) {
168  // FIXME: Support negative field widths.
169  if (argIndex) {
170    FS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
171  }
172  else {
173    const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
174                                                 analyze_printf::FieldWidthPos);
175    if (Amt.isInvalid())
176      return true;
177    FS.setFieldWidth(Amt);
178  }
179  return false;
180}
181
182static bool ParseArgPosition(FormatStringHandler &H,
183                             FormatSpecifier &FS, const char *Start,
184                             const char *&Beg, const char *E) {
185
186  using namespace clang::analyze_printf;
187  const char *I = Beg;
188
189  const OptionalAmount &Amt = ParseAmount(I, E);
190
191  if (I == E) {
192    // No more characters left?
193    H.HandleIncompleteFormatSpecifier(Start, E - Start);
194    return true;
195  }
196
197  if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
198    // Special case: '%0$', since this is an easy mistake.
199    if (Amt.getConstantAmount() == 0) {
200      H.HandleZeroPosition(Start, I - Start);
201      return true;
202    }
203
204    FS.setArgIndex(Amt.getConstantAmount() - 1);
205    FS.setUsesPositionalArg();
206    // Update the caller's pointer if we decided to consume
207    // these characters.
208    Beg = I;
209    return false;
210  }
211
212  return false;
213}
214
215static FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
216                                                  const char *&Beg,
217                                                  const char *E,
218                                                  unsigned &argIndex) {
219
220  using namespace clang::analyze_printf;
221
222  const char *I = Beg;
223  const char *Start = 0;
224  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
225
226  // Look for a '%' character that indicates the start of a format specifier.
227  for ( ; I != E ; ++I) {
228    char c = *I;
229    if (c == '\0') {
230      // Detect spurious null characters, which are likely errors.
231      H.HandleNullChar(I);
232      return true;
233    }
234    if (c == '%') {
235      Start = I++;  // Record the start of the format specifier.
236      break;
237    }
238  }
239
240  // No format specifier found?
241  if (!Start)
242    return false;
243
244  if (I == E) {
245    // No more characters left?
246    H.HandleIncompleteFormatSpecifier(Start, E - Start);
247    return true;
248  }
249
250  FormatSpecifier FS;
251  if (ParseArgPosition(H, FS, Start, I, E))
252    return true;
253
254  if (I == E) {
255    // No more characters left?
256    H.HandleIncompleteFormatSpecifier(Start, E - Start);
257    return true;
258  }
259
260  // Look for flags (if any).
261  bool hasMore = true;
262  for ( ; I != E; ++I) {
263    switch (*I) {
264      default: hasMore = false; break;
265      case '-': FS.setIsLeftJustified(I); break;
266      case '+': FS.setHasPlusPrefix(I); break;
267      case ' ': FS.setHasSpacePrefix(I); break;
268      case '#': FS.setHasAlternativeForm(I); break;
269      case '0': FS.setHasLeadingZeros(I); break;
270    }
271    if (!hasMore)
272      break;
273  }
274
275  if (I == E) {
276    // No more characters left?
277    H.HandleIncompleteFormatSpecifier(Start, E - Start);
278    return true;
279  }
280
281  // Look for the field width (if any).
282  if (ParseFieldWidth(H, FS, Start, I, E,
283                      FS.usesPositionalArg() ? 0 : &argIndex))
284    return true;
285
286  if (I == E) {
287    // No more characters left?
288    H.HandleIncompleteFormatSpecifier(Start, E - Start);
289    return true;
290  }
291
292  // Look for the precision (if any).
293  if (*I == '.') {
294    ++I;
295    if (I == E) {
296      H.HandleIncompleteFormatSpecifier(Start, E - Start);
297      return true;
298    }
299
300    if (ParsePrecision(H, FS, Start, I, E,
301                       FS.usesPositionalArg() ? 0 : &argIndex))
302      return true;
303
304    if (I == E) {
305      // No more characters left?
306      H.HandleIncompleteFormatSpecifier(Start, E - Start);
307      return true;
308    }
309  }
310
311  // Look for the length modifier.
312  LengthModifier::Kind lmKind = LengthModifier::None;
313  const char *lmPosition = I;
314  switch (*I) {
315    default:
316      break;
317    case 'h':
318      ++I;
319      lmKind = (I != E && *I == 'h') ?
320          ++I, LengthModifier::AsChar : LengthModifier::AsShort;
321      break;
322    case 'l':
323      ++I;
324      lmKind = (I != E && *I == 'l') ?
325          ++I, LengthModifier::AsLongLong : LengthModifier::AsLong;
326      break;
327    case 'j': lmKind = LengthModifier::AsIntMax;     ++I; break;
328    case 'z': lmKind = LengthModifier::AsSizeT;      ++I; break;
329    case 't': lmKind = LengthModifier::AsPtrDiff;    ++I; break;
330    case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
331    case 'q': lmKind = LengthModifier::AsLongLong;   ++I; break;
332  }
333  LengthModifier lm(lmPosition, lmKind);
334  FS.setLengthModifier(lm);
335
336  if (I == E) {
337    // No more characters left?
338    H.HandleIncompleteFormatSpecifier(Start, E - Start);
339    return true;
340  }
341
342  if (*I == '\0') {
343    // Detect spurious null characters, which are likely errors.
344    H.HandleNullChar(I);
345    return true;
346  }
347
348  // Finally, look for the conversion specifier.
349  const char *conversionPosition = I++;
350  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
351  switch (*conversionPosition) {
352    default:
353      break;
354    // C99: 7.19.6.1 (section 8).
355    case '%': k = ConversionSpecifier::PercentArg;   break;
356    case 'A': k = ConversionSpecifier::AArg; break;
357    case 'E': k = ConversionSpecifier::EArg; break;
358    case 'F': k = ConversionSpecifier::FArg; break;
359    case 'G': k = ConversionSpecifier::GArg; break;
360    case 'X': k = ConversionSpecifier::XArg; break;
361    case 'a': k = ConversionSpecifier::aArg; break;
362    case 'c': k = ConversionSpecifier::IntAsCharArg; break;
363    case 'd': k = ConversionSpecifier::dArg; break;
364    case 'e': k = ConversionSpecifier::eArg; break;
365    case 'f': k = ConversionSpecifier::fArg; break;
366    case 'g': k = ConversionSpecifier::gArg; break;
367    case 'i': k = ConversionSpecifier::iArg; break;
368    case 'n': k = ConversionSpecifier::OutIntPtrArg; break;
369    case 'o': k = ConversionSpecifier::oArg; break;
370    case 'p': k = ConversionSpecifier::VoidPtrArg;   break;
371    case 's': k = ConversionSpecifier::CStrArg;      break;
372    case 'u': k = ConversionSpecifier::uArg; break;
373    case 'x': k = ConversionSpecifier::xArg; break;
374    // Mac OS X (unicode) specific
375    case 'C': k = ConversionSpecifier::CArg; break;
376    case 'S': k = ConversionSpecifier::UnicodeStrArg; break;
377    // Objective-C.
378    case '@': k = ConversionSpecifier::ObjCObjArg; break;
379    // Glibc specific.
380    case 'm': k = ConversionSpecifier::PrintErrno; break;
381  }
382  ConversionSpecifier CS(conversionPosition, k);
383  FS.setConversionSpecifier(CS);
384  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
385    FS.setArgIndex(argIndex++);
386
387  if (k == ConversionSpecifier::InvalidSpecifier) {
388    // Assume the conversion takes one argument.
389    return !H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg);
390  }
391  return FormatSpecifierResult(Start, FS);
392}
393
394bool clang::analyze_printf::ParseFormatString(FormatStringHandler &H,
395                       const char *I, const char *E) {
396
397  unsigned argIndex = 0;
398
399  // Keep looking for a format specifier until we have exhausted the string.
400  while (I != E) {
401    const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E, argIndex);
402    // Did a fail-stop error of any kind occur when parsing the specifier?
403    // If so, don't do any more processing.
404    if (FSR.shouldStop())
405      return true;;
406    // Did we exhaust the string or encounter an error that
407    // we can recover from?
408    if (!FSR.hasValue())
409      continue;
410    // We have a format specifier.  Pass it to the callback.
411    if (!H.HandleFormatSpecifier(FSR.getValue(), FSR.getStart(),
412                                 I - FSR.getStart()))
413      return true;
414  }
415  assert(I == E && "Format string not exhausted");
416  return false;
417}
418
419FormatStringHandler::~FormatStringHandler() {}
420
421//===----------------------------------------------------------------------===//
422// Methods on ArgTypeResult.
423//===----------------------------------------------------------------------===//
424
425bool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const {
426  switch (K) {
427    case InvalidTy:
428      assert(false && "ArgTypeResult must be valid");
429      return true;
430
431    case UnknownTy:
432      return true;
433
434    case SpecificTy: {
435      argTy = C.getCanonicalType(argTy).getUnqualifiedType();
436      if (T == argTy)
437        return true;
438      if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
439        switch (BT->getKind()) {
440          default:
441            break;
442          case BuiltinType::Char_S:
443          case BuiltinType::SChar:
444            return T == C.UnsignedCharTy;
445          case BuiltinType::Char_U:
446          case BuiltinType::UChar:
447            return T == C.SignedCharTy;
448          case BuiltinType::Short:
449            return T == C.UnsignedShortTy;
450          case BuiltinType::UShort:
451            return T == C.ShortTy;
452          case BuiltinType::Int:
453            return T == C.UnsignedIntTy;
454          case BuiltinType::UInt:
455            return T == C.IntTy;
456          case BuiltinType::Long:
457            return T == C.UnsignedLongTy;
458          case BuiltinType::ULong:
459            return T == C.LongTy;
460          case BuiltinType::LongLong:
461            return T == C.UnsignedLongLongTy;
462          case BuiltinType::ULongLong:
463            return T == C.LongLongTy;
464        }
465      return false;
466    }
467
468    case CStrTy: {
469      const PointerType *PT = argTy->getAs<PointerType>();
470      if (!PT)
471        return false;
472      QualType pointeeTy = PT->getPointeeType();
473      if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
474        switch (BT->getKind()) {
475          case BuiltinType::Void:
476          case BuiltinType::Char_U:
477          case BuiltinType::UChar:
478          case BuiltinType::Char_S:
479          case BuiltinType::SChar:
480            return true;
481          default:
482            break;
483        }
484
485      return false;
486    }
487
488    case WCStrTy: {
489      const PointerType *PT = argTy->getAs<PointerType>();
490      if (!PT)
491        return false;
492      QualType pointeeTy =
493        C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
494      return pointeeTy == C.getWCharType();
495    }
496
497    case CPointerTy:
498      return argTy->getAs<PointerType>() != NULL ||
499      	     argTy->getAs<ObjCObjectPointerType>() != NULL;
500
501    case ObjCPointerTy:
502      return argTy->getAs<ObjCObjectPointerType>() != NULL;
503  }
504
505  // FIXME: Should be unreachable, but Clang is currently emitting
506  // a warning.
507  return false;
508}
509
510QualType ArgTypeResult::getRepresentativeType(ASTContext &C) const {
511  switch (K) {
512    case InvalidTy:
513      assert(false && "No representative type for Invalid ArgTypeResult");
514      // Fall-through.
515    case UnknownTy:
516      return QualType();
517    case SpecificTy:
518      return T;
519    case CStrTy:
520      return C.getPointerType(C.CharTy);
521    case WCStrTy:
522      return C.getPointerType(C.getWCharType());
523    case ObjCPointerTy:
524      return C.ObjCBuiltinIdTy;
525    case CPointerTy:
526      return C.VoidPtrTy;
527  }
528
529  // FIXME: Should be unreachable, but Clang is currently emitting
530  // a warning.
531  return QualType();
532}
533
534//===----------------------------------------------------------------------===//
535// Methods on OptionalAmount.
536//===----------------------------------------------------------------------===//
537
538ArgTypeResult OptionalAmount::getArgType(ASTContext &Ctx) const {
539  return Ctx.IntTy;
540}
541
542//===----------------------------------------------------------------------===//
543// Methods on ConversionSpecifier.
544//===----------------------------------------------------------------------===//
545const char *ConversionSpecifier::toString() const {
546  switch (kind) {
547  case dArg: return "d";
548  case iArg: return "i";
549  case oArg: return "o";
550  case uArg: return "u";
551  case xArg: return "x";
552  case XArg: return "X";
553  case fArg: return "f";
554  case FArg: return "F";
555  case eArg: return "e";
556  case EArg: return "E";
557  case gArg: return "g";
558  case GArg: return "G";
559  case aArg: return "a";
560  case AArg: return "A";
561  case IntAsCharArg:     return "c";
562  case CStrArg:          return "s";
563  case VoidPtrArg:       return "p";
564  case OutIntPtrArg:     return "n";
565  case PercentArg:       return "%";
566  case InvalidSpecifier: return NULL;
567
568  // MacOS X unicode extensions.
569  case CArg:          return "C";
570  case UnicodeStrArg: return "S";
571
572  // Objective-C specific specifiers.
573  case ObjCObjArg: return "@";
574
575  // GlibC specific specifiers.
576  case PrintErrno: return "m";
577  }
578  return NULL;
579}
580
581//===----------------------------------------------------------------------===//
582// Methods on LengthModifier.
583//===----------------------------------------------------------------------===//
584
585const char *LengthModifier::toString() const {
586  switch (kind) {
587  case AsChar:
588    return "hh";
589  case AsShort:
590    return "h";
591  case AsLong: // or AsWideChar
592    return "l";
593  case AsLongLong:
594    return "ll";
595  case AsIntMax:
596    return "j";
597  case AsSizeT:
598    return "z";
599  case AsPtrDiff:
600    return "t";
601  case AsLongDouble:
602    return "L";
603  case None:
604    return "";
605  }
606  return NULL;
607}
608
609//===----------------------------------------------------------------------===//
610// Methods on OptionalAmount.
611//===----------------------------------------------------------------------===//
612
613void OptionalAmount::toString(llvm::raw_ostream &os) const {
614  switch (hs) {
615  case Invalid:
616  case NotSpecified:
617    return;
618  case Arg:
619    if (UsesDotPrefix)
620        os << ".";
621    if (usesPositionalArg())
622      os << "*" << getPositionalArgIndex() << "$";
623    else
624      os << "*";
625    break;
626  case Constant:
627    if (UsesDotPrefix)
628        os << ".";
629    os << amt;
630    break;
631  }
632}
633
634//===----------------------------------------------------------------------===//
635// Methods on FormatSpecifier.
636//===----------------------------------------------------------------------===//
637
638ArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const {
639  if (!CS.consumesDataArgument())
640    return ArgTypeResult::Invalid();
641
642  if (CS.isIntArg())
643    switch (LM.getKind()) {
644      case LengthModifier::AsLongDouble:
645        return ArgTypeResult::Invalid();
646      case LengthModifier::None: return Ctx.IntTy;
647      case LengthModifier::AsChar: return Ctx.SignedCharTy;
648      case LengthModifier::AsShort: return Ctx.ShortTy;
649      case LengthModifier::AsLong: return Ctx.LongTy;
650      case LengthModifier::AsLongLong: return Ctx.LongLongTy;
651      case LengthModifier::AsIntMax:
652        // FIXME: Return unknown for now.
653        return ArgTypeResult();
654      case LengthModifier::AsSizeT: return Ctx.getSizeType();
655      case LengthModifier::AsPtrDiff: return Ctx.getPointerDiffType();
656    }
657
658  if (CS.isUIntArg())
659    switch (LM.getKind()) {
660      case LengthModifier::AsLongDouble:
661        return ArgTypeResult::Invalid();
662      case LengthModifier::None: return Ctx.UnsignedIntTy;
663      case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
664      case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
665      case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
666      case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy;
667      case LengthModifier::AsIntMax:
668        // FIXME: Return unknown for now.
669        return ArgTypeResult();
670      case LengthModifier::AsSizeT:
671        // FIXME: How to get the corresponding unsigned
672        // version of size_t?
673        return ArgTypeResult();
674      case LengthModifier::AsPtrDiff:
675        // FIXME: How to get the corresponding unsigned
676        // version of ptrdiff_t?
677        return ArgTypeResult();
678    }
679
680  if (CS.isDoubleArg()) {
681    if (LM.getKind() == LengthModifier::AsLongDouble)
682      return Ctx.LongDoubleTy;
683    return Ctx.DoubleTy;
684  }
685
686  switch (CS.getKind()) {
687    case ConversionSpecifier::CStrArg:
688      return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ?
689          ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy);
690    case ConversionSpecifier::UnicodeStrArg:
691      // FIXME: This appears to be Mac OS X specific.
692      return ArgTypeResult::WCStrTy;
693    case ConversionSpecifier::CArg:
694      return Ctx.WCharTy;
695    case ConversionSpecifier::VoidPtrArg:
696      return ArgTypeResult::CPointerTy;
697    default:
698      break;
699  }
700
701  // FIXME: Handle other cases.
702  return ArgTypeResult();
703}
704
705bool FormatSpecifier::fixType(QualType QT) {
706  // Handle strings first (char *, wchar_t *)
707  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
708    CS.setKind(ConversionSpecifier::CStrArg);
709
710    // Disable irrelevant flags
711    HasAlternativeForm = 0;
712    HasLeadingZeroes = 0;
713
714    // Set the long length modifier for wide characters
715    if (QT->getPointeeType()->isWideCharType())
716      LM.setKind(LengthModifier::AsWideChar);
717
718    return true;
719  }
720
721  // We can only work with builtin types.
722  if (!QT->isBuiltinType())
723    return false;
724
725  // Everything else should be a base type
726  const BuiltinType *BT = QT->getAs<BuiltinType>();
727
728  // Set length modifier
729  switch (BT->getKind()) {
730  default:
731    // The rest of the conversions are either optional or for non-builtin types
732    LM.setKind(LengthModifier::None);
733    break;
734
735  case BuiltinType::WChar:
736  case BuiltinType::Long:
737  case BuiltinType::ULong:
738    LM.setKind(LengthModifier::AsLong);
739    break;
740
741  case BuiltinType::LongLong:
742  case BuiltinType::ULongLong:
743    LM.setKind(LengthModifier::AsLongLong);
744    break;
745
746  case BuiltinType::LongDouble:
747    LM.setKind(LengthModifier::AsLongDouble);
748    break;
749  }
750
751  // Set conversion specifier and disable any flags which do not apply to it.
752  if (QT->isAnyCharacterType()) {
753    CS.setKind(ConversionSpecifier::IntAsCharArg);
754    Precision.setHowSpecified(OptionalAmount::NotSpecified);
755    HasAlternativeForm = 0;
756    HasLeadingZeroes = 0;
757    HasPlusPrefix = 0;
758  }
759  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
760  else if (QT->isRealFloatingType()) {
761    CS.setKind(ConversionSpecifier::fArg);
762  }
763  else if (QT->isPointerType()) {
764    CS.setKind(ConversionSpecifier::VoidPtrArg);
765    Precision.setHowSpecified(OptionalAmount::NotSpecified);
766    HasAlternativeForm = 0;
767    HasLeadingZeroes = 0;
768    HasPlusPrefix = 0;
769  }
770  else if (QT->isSignedIntegerType()) {
771    CS.setKind(ConversionSpecifier::dArg);
772    HasAlternativeForm = 0;
773  }
774  else if (QT->isUnsignedIntegerType()) {
775    CS.setKind(ConversionSpecifier::uArg);
776    HasAlternativeForm = 0;
777    HasPlusPrefix = 0;
778  }
779  else {
780    return false;
781  }
782
783  return true;
784}
785
786void FormatSpecifier::toString(llvm::raw_ostream &os) const {
787  // Whilst some features have no defined order, we are using the order
788  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) �7.19.6.1)
789  os << "%";
790
791  // Positional args
792  if (usesPositionalArg()) {
793    os << getPositionalArgIndex() << "$";
794  }
795
796  // Conversion flags
797  if (IsLeftJustified)    os << "-";
798  if (HasPlusPrefix)      os << "+";
799  if (HasSpacePrefix)     os << " ";
800  if (HasAlternativeForm) os << "#";
801  if (HasLeadingZeroes)   os << "0";
802
803  // Minimum field width
804  FieldWidth.toString(os);
805  // Precision
806  Precision.toString(os);
807  // Length modifier
808  os << LM.toString();
809  // Conversion specifier
810  os << CS.toString();
811}
812
813bool FormatSpecifier::hasValidPlusPrefix() const {
814  if (!HasPlusPrefix)
815    return true;
816
817  // The plus prefix only makes sense for signed conversions
818  switch (CS.getKind()) {
819  case ConversionSpecifier::dArg:
820  case ConversionSpecifier::iArg:
821  case ConversionSpecifier::fArg:
822  case ConversionSpecifier::FArg:
823  case ConversionSpecifier::eArg:
824  case ConversionSpecifier::EArg:
825  case ConversionSpecifier::gArg:
826  case ConversionSpecifier::GArg:
827  case ConversionSpecifier::aArg:
828  case ConversionSpecifier::AArg:
829    return true;
830
831  default:
832    return false;
833  }
834}
835
836bool FormatSpecifier::hasValidAlternativeForm() const {
837  if (!HasAlternativeForm)
838    return true;
839
840  // Alternate form flag only valid with the oxaAeEfFgG conversions
841  switch (CS.getKind()) {
842  case ConversionSpecifier::oArg:
843  case ConversionSpecifier::xArg:
844  case ConversionSpecifier::aArg:
845  case ConversionSpecifier::AArg:
846  case ConversionSpecifier::eArg:
847  case ConversionSpecifier::EArg:
848  case ConversionSpecifier::fArg:
849  case ConversionSpecifier::FArg:
850  case ConversionSpecifier::gArg:
851  case ConversionSpecifier::GArg:
852    return true;
853
854  default:
855    return false;
856  }
857}
858
859bool FormatSpecifier::hasValidLeadingZeros() const {
860  if (!HasLeadingZeroes)
861    return true;
862
863  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
864  switch (CS.getKind()) {
865  case ConversionSpecifier::dArg:
866  case ConversionSpecifier::iArg:
867  case ConversionSpecifier::oArg:
868  case ConversionSpecifier::uArg:
869  case ConversionSpecifier::xArg:
870  case ConversionSpecifier::XArg:
871  case ConversionSpecifier::aArg:
872  case ConversionSpecifier::AArg:
873  case ConversionSpecifier::eArg:
874  case ConversionSpecifier::EArg:
875  case ConversionSpecifier::fArg:
876  case ConversionSpecifier::FArg:
877  case ConversionSpecifier::gArg:
878  case ConversionSpecifier::GArg:
879    return true;
880
881  default:
882    return false;
883  }
884}
885
886bool FormatSpecifier::hasValidSpacePrefix() const {
887  if (!HasSpacePrefix)
888    return true;
889
890  // The space prefix only makes sense for signed conversions
891  switch (CS.getKind()) {
892  case ConversionSpecifier::dArg:
893  case ConversionSpecifier::iArg:
894  case ConversionSpecifier::fArg:
895  case ConversionSpecifier::FArg:
896  case ConversionSpecifier::eArg:
897  case ConversionSpecifier::EArg:
898  case ConversionSpecifier::gArg:
899  case ConversionSpecifier::GArg:
900  case ConversionSpecifier::aArg:
901  case ConversionSpecifier::AArg:
902    return true;
903
904  default:
905    return false;
906  }
907}
908
909bool FormatSpecifier::hasValidLeftJustified() const {
910  if (!IsLeftJustified)
911    return true;
912
913  // The left justified flag is valid for all conversions except n
914  switch (CS.getKind()) {
915  case ConversionSpecifier::OutIntPtrArg:
916    return false;
917
918  default:
919    return true;
920  }
921}
922
923bool FormatSpecifier::hasValidLengthModifier() const {
924  switch (LM.getKind()) {
925  case LengthModifier::None:
926    return true;
927
928  // Handle most integer flags
929  case LengthModifier::AsChar:
930  case LengthModifier::AsShort:
931  case LengthModifier::AsLongLong:
932  case LengthModifier::AsIntMax:
933  case LengthModifier::AsSizeT:
934  case LengthModifier::AsPtrDiff:
935    switch (CS.getKind()) {
936    case ConversionSpecifier::dArg:
937    case ConversionSpecifier::iArg:
938    case ConversionSpecifier::oArg:
939    case ConversionSpecifier::uArg:
940    case ConversionSpecifier::xArg:
941    case ConversionSpecifier::XArg:
942    case ConversionSpecifier::OutIntPtrArg:
943      return true;
944    default:
945      return false;
946    }
947
948  // Handle 'l' flag
949  case LengthModifier::AsLong:
950    switch (CS.getKind()) {
951    case ConversionSpecifier::dArg:
952    case ConversionSpecifier::iArg:
953    case ConversionSpecifier::oArg:
954    case ConversionSpecifier::uArg:
955    case ConversionSpecifier::xArg:
956    case ConversionSpecifier::XArg:
957    case ConversionSpecifier::aArg:
958    case ConversionSpecifier::AArg:
959    case ConversionSpecifier::fArg:
960    case ConversionSpecifier::FArg:
961    case ConversionSpecifier::eArg:
962    case ConversionSpecifier::EArg:
963    case ConversionSpecifier::gArg:
964    case ConversionSpecifier::GArg:
965    case ConversionSpecifier::OutIntPtrArg:
966    case ConversionSpecifier::IntAsCharArg:
967    case ConversionSpecifier::CStrArg:
968      return true;
969    default:
970      return false;
971    }
972
973  case LengthModifier::AsLongDouble:
974    switch (CS.getKind()) {
975    case ConversionSpecifier::aArg:
976    case ConversionSpecifier::AArg:
977    case ConversionSpecifier::fArg:
978    case ConversionSpecifier::FArg:
979    case ConversionSpecifier::eArg:
980    case ConversionSpecifier::EArg:
981    case ConversionSpecifier::gArg:
982    case ConversionSpecifier::GArg:
983      return true;
984    default:
985      return false;
986    }
987  }
988  return false;
989}
990
991bool FormatSpecifier::hasValidPrecision() const {
992  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
993    return true;
994
995  // Precision is only valid with the diouxXaAeEfFgGs conversions
996  switch (CS.getKind()) {
997  case ConversionSpecifier::dArg:
998  case ConversionSpecifier::iArg:
999  case ConversionSpecifier::oArg:
1000  case ConversionSpecifier::uArg:
1001  case ConversionSpecifier::xArg:
1002  case ConversionSpecifier::XArg:
1003  case ConversionSpecifier::aArg:
1004  case ConversionSpecifier::AArg:
1005  case ConversionSpecifier::eArg:
1006  case ConversionSpecifier::EArg:
1007  case ConversionSpecifier::fArg:
1008  case ConversionSpecifier::FArg:
1009  case ConversionSpecifier::gArg:
1010  case ConversionSpecifier::GArg:
1011  case ConversionSpecifier::CStrArg:
1012    return true;
1013
1014  default:
1015    return false;
1016  }
1017}
1018bool FormatSpecifier::hasValidFieldWidth() const {
1019  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1020      return true;
1021
1022  // The field width is valid for all conversions except n
1023  switch (CS.getKind()) {
1024  case ConversionSpecifier::OutIntPtrArg:
1025    return false;
1026
1027  default:
1028    return true;
1029  }
1030}
1031