PrintfFormatString.cpp revision 87260c7eabf88eb2009ba2ba20150cd897483241
18f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//= PrintfFormatStrings.cpp - Analysis of printf format strings --*- C++ -*-==//
28f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//
38f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//                     The LLVM Compiler Infrastructure
48f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//
58f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// This file is distributed under the University of Illinois Open Source
68f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// License. See LICENSE.TXT for details.
78f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//
88f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//===----------------------------------------------------------------------===//
98f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//
108f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// Handling of format string in printf and friends.  The structure of format
118f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// strings for fprintf() are described in C99 7.19.6.1.
128f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//
138f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//===----------------------------------------------------------------------===//
148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
158f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek#include "clang/Analysis/Analyses/PrintfFormatString.h"
1633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek#include "clang/AST/ASTContext.h"
178f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
184b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenekusing clang::analyze_printf::FormatSpecifier;
194b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenekusing clang::analyze_printf::OptionalAmount;
2033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenekusing clang::analyze_printf::ArgTypeResult;
2174d56a168966ff015824279a24aaf566180ed97dTed Kremenekusing clang::analyze_printf::FormatStringHandler;
22808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenekusing namespace clang;
238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
248f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremeneknamespace {
258f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekclass FormatSpecifierResult {
268f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  FormatSpecifier FS;
278f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  const char *Start;
2826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  bool Stop;
298f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekpublic:
3026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  FormatSpecifierResult(bool stop = false)
3126ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    : Start(0), Stop(stop) {}
328f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  FormatSpecifierResult(const char *start,
33d2dcece5882215e92a80bff8a7b7fd2fd81d7086Ted Kremenek                        const FormatSpecifier &fs)
3426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    : FS(fs), Start(start), Stop(false) {}
358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
378f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  const char *getStart() const { return Start; }
3826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  bool shouldStop() const { return Stop; }
398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  bool hasValue() const { return Start != 0; }
408f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  const FormatSpecifier &getValue() const {
418f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    assert(hasValue());
428f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return FS;
438f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
44d2dcece5882215e92a80bff8a7b7fd2fd81d7086Ted Kremenek  const FormatSpecifier &getValue() { return FS; }
458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek};
468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} // end anonymous namespace
478f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
488f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenektemplate <typename T>
498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekclass UpdateOnReturn {
508f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  T &ValueToUpdate;
518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  const T &ValueToCopy;
528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekpublic:
538f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  UpdateOnReturn(T &valueToUpdate, const T &valueToCopy)
548f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {}
554e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
568f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  ~UpdateOnReturn() {
578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    ValueToUpdate = ValueToCopy;
588f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
594e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek};
604e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
614e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
624e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods for parsing format strings.
634e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
648f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
658f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekstatic OptionalAmount ParseAmount(const char *&Beg, const char *E) {
668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  const char *I = Beg;
678f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
684e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  bool foundDigits = false;
708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  unsigned accumulator = 0;
718f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
728f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  for ( ; I != E; ++I) {
738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    char c = *I;
748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (c >= '0' && c <= '9') {
758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      foundDigits = true;
768f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      accumulator += (accumulator * 10) + (c - '0');
778f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      continue;
788f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
798f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
808f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (foundDigits)
810d27735c51f5bd392e673cf39a675e14e9442387Ted Kremenek      return OptionalAmount(accumulator, Beg);
824e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
830d27735c51f5bd392e673cf39a675e14e9442387Ted Kremenek    if (c == '*') {
840d27735c51f5bd392e673cf39a675e14e9442387Ted Kremenek      ++I;
850d27735c51f5bd392e673cf39a675e14e9442387Ted Kremenek      return OptionalAmount(OptionalAmount::Arg, Beg);
860d27735c51f5bd392e673cf39a675e14e9442387Ted Kremenek    }
874e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
888f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    break;
898f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
904e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
914e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  return OptionalAmount();
928f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
938f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
94808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenekstatic FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H,
9574d56a168966ff015824279a24aaf566180ed97dTed Kremenek                                                  const char *&Beg,
9674d56a168966ff015824279a24aaf566180ed97dTed Kremenek                                                  const char *E) {
974e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
984b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenek  using namespace clang::analyze_printf;
994e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1008f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  const char *I = Beg;
101c7ae51a3cd9460db8280e8623c90614f246e46d2Ted Kremenek  const char *Start = 0;
1028f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
1038f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1048f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for a '%' character that indicates the start of a format specifier.
105e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek  for ( ; I != E ; ++I) {
1068f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    char c = *I;
1078f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (c == '\0') {
1088f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      // Detect spurious null characters, which are likely errors.
1098f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      H.HandleNullChar(I);
1108f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1118f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1128f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (c == '%') {
113e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek      Start = I++;  // Record the start of the format specifier.
1148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
1158f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1168f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1174e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1188f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // No format specifier found?
1198f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (!Start)
1208f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return false;
1214e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1228f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
124808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek    H.HandleIncompleteFormatSpecifier(Start, E - Start);
1258f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1268f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1274e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1288f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  FormatSpecifier FS;
1294e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1308f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for flags (if any).
1318f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  bool hasMore = true;
1328f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  for ( ; I != E; ++I) {
1338f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    switch (*I) {
1348f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      default: hasMore = false; break;
1358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      case '-': FS.setIsLeftJustified(); break;
1368f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      case '+': FS.setHasPlusPrefix(); break;
1378f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      case ' ': FS.setHasSpacePrefix(); break;
1388f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      case '#': FS.setHasAlternativeForm(); break;
1398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      case '0': FS.setHasLeadingZeros(); break;
1408f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1418f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (!hasMore)
1428f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
1434e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
1448f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
147808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek    H.HandleIncompleteFormatSpecifier(Start, E - Start);
1488f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1504e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for the field width (if any).
1528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  FS.setFieldWidth(ParseAmount(I, E));
1534e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1548f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1558f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
156808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek    H.HandleIncompleteFormatSpecifier(Start, E - Start);
1578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1584e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
1594e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1604e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  // Look for the precision (if any).
1618f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (*I == '.') {
162808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek    ++I;
1638f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (I == E) {
164808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek      H.HandleIncompleteFormatSpecifier(Start, E - Start);
1658f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1674e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1688f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    FS.setPrecision(ParseAmount(I, E));
1698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (I == E) {
1718f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      // No more characters left?
172808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek      H.HandleIncompleteFormatSpecifier(Start, E - Start);
1738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1768f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1778f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for the length modifier.
1788f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  LengthModifier lm = None;
1798f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  switch (*I) {
1808f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    default:
1818f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
1828f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    case 'h':
1838f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      ++I;
1844e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      lm = (I != E && *I == 'h') ? ++I, AsChar : AsShort;
1858f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
1868f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    case 'l':
1878f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      ++I;
1888f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      lm = (I != E && *I == 'l') ? ++I, AsLongLong : AsLong;
1898f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
1908f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    case 'j': lm = AsIntMax;     ++I; break;
1918f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    case 'z': lm = AsSizeT;      ++I; break;
1928f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    case 't': lm = AsPtrDiff;    ++I; break;
1938f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    case 'L': lm = AsLongDouble; ++I; break;
19401aefc6d20fbfd50bfb83926226dee86dd31c9c5Daniel Dunbar    case 'q': lm = AsLongLong;   ++I; break;
1958f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1968f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  FS.setLengthModifier(lm);
1974e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1988f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1998f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
200808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek    H.HandleIncompleteFormatSpecifier(Start, E - Start);
2018f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
2028f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
203df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek
2044dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek  if (*I == '\0') {
205df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    // Detect spurious null characters, which are likely errors.
206df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    H.HandleNullChar(I);
207df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    return true;
2084dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek  }
2094e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
2108f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Finally, look for the conversion specifier.
211a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  const char *conversionPosition = I++;
21226ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
213a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  switch (*conversionPosition) {
2148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    default:
21526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek      break;
216c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek    // C99: 7.19.6.1 (section 8).
21787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case '%': k = ConversionSpecifier::PercentArg;   break;
21887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'A': k = ConversionSpecifier::AArg; break;
219a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'E': k = ConversionSpecifier::EArg; break;
22087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'F': k = ConversionSpecifier::FArg; break;
221a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'G': k = ConversionSpecifier::GArg; break;
22287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'X': k = ConversionSpecifier::XArg; break;
223a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'a': k = ConversionSpecifier::aArg; break;
224a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'c': k = ConversionSpecifier::IntAsCharArg; break;
22587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'd': k = ConversionSpecifier::dArg; break;
22687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'e': k = ConversionSpecifier::eArg; break;
22787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'f': k = ConversionSpecifier::fArg; break;
22887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'g': k = ConversionSpecifier::gArg; break;
22987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'i': k = ConversionSpecifier::iArg; break;
230a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'n': k = ConversionSpecifier::OutIntPtrArg; break;
23187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'o': k = ConversionSpecifier::oArg; break;
23287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'p': k = ConversionSpecifier::VoidPtrArg;   break;
23387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 's': k = ConversionSpecifier::CStrArg;      break;
23487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'u': k = ConversionSpecifier::uArg; break;
23587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'x': k = ConversionSpecifier::xArg; break;
23687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    // Mac OS X (unicode) specific
23787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'C': k = ConversionSpecifier::CArg; break;
23887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'S': k = ConversionSpecifier::UnicodeStrArg; break;
239c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek    // Objective-C.
2404dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek    case '@': k = ConversionSpecifier::ObjCObjArg; break;
241df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    // Glibc specific.
2424dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek    case 'm': k = ConversionSpecifier::PrintErrno; break;
2438f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
244a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  FS.setConversionSpecifier(ConversionSpecifier(conversionPosition, k));
24526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek
24626ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  if (k == ConversionSpecifier::InvalidSpecifier) {
24726ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg);
24826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    return false; // Keep processing format specifiers.
24926ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  }
2508f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  return FormatSpecifierResult(Start, FS);
2518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
2528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
25374d56a168966ff015824279a24aaf566180ed97dTed Kremenekbool clang::analyze_printf::ParseFormatString(FormatStringHandler &H,
254a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek                       const char *I, const char *E) {
2558f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Keep looking for a format specifier until we have exhausted the string.
2568f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  while (I != E) {
2578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E);
25826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // Did a fail-stop error of any kind occur when parsing the specifier?
25926ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // If so, don't do any more processing.
26026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    if (FSR.shouldStop())
2618f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;;
26226ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // Did we exhaust the string or encounter an error that
26326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // we can recover from?
2648f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (!FSR.hasValue())
26526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek      continue;
2668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // We have a format specifier.  Pass it to the callback.
267a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    if (!H.HandleFormatSpecifier(FSR.getValue(), FSR.getStart(),
268a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek                                 I - FSR.getStart()))
2694dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek      return true;
2704e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
2714e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  assert(I == E && "Format string not exhausted");
2728f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  return false;
2738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
2748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
2758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted KremenekFormatStringHandler::~FormatStringHandler() {}
27633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
27733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===//
2784e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods on ArgTypeResult.
2794e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
2804e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
2814e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenekbool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const {
2824e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  assert(isValid());
2834e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
2844e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  if (K == UnknownTy)
2854e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    return true;
2864e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
2874e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  if (K == SpecificTy) {
2884e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    argTy = C.getCanonicalType(argTy).getUnqualifiedType();
2894e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
2904e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    if (T == argTy)
2914e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      return true;
2924e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
2934e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
2944e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      switch (BT->getKind()) {
2954e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        default:
2964e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          break;
2974e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::Char_S:
2984e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::SChar:
2994e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return T == C.UnsignedCharTy;
3004e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::Char_U:
3014e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::UChar:
3024e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return T == C.SignedCharTy;
3034e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::Short:
3044e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return T == C.UnsignedShortTy;
3054e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::UShort:
3064e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return T == C.ShortTy;
3074e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::Int:
3084e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return T == C.UnsignedIntTy;
3094e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::UInt:
3104e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return T == C.IntTy;
3114e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::Long:
3124e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return T == C.UnsignedLongTy;
3134e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::ULong:
3144e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return T == C.LongTy;
3154e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::LongLong:
3164e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return T == C.UnsignedLongLongTy;
3174e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::ULongLong:
3184e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return T == C.LongLongTy;
3194e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      }
3204e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3214e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    return false;
3224e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
3234e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3244e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  if (K == CStrTy) {
3254e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    const PointerType *PT = argTy->getAs<PointerType>();
3264e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    if (!PT)
3274e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      return false;
3284e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3294e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    QualType pointeeTy = PT->getPointeeType();
3304e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3314e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
3324e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      switch (BT->getKind()) {
3334e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::Void:
3344e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::Char_U:
3354e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::UChar:
3364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::Char_S:
3374e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        case BuiltinType::SChar:
3384e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          return true;
3394e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek        default:
3404e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek          break;
3414e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      }
3424e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3434e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    return false;
3444e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
3454e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3464e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  if (K == WCStrTy) {
3474e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    const PointerType *PT = argTy->getAs<PointerType>();
3484e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    if (!PT)
3494e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      return false;
3504e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
35187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    QualType pointeeTy =
35287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
35387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek
35487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    return pointeeTy == C.getWCharType();
3554e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
3564e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3574e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  return false;
3584e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek}
3594e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3604e4b30ec62d78b24e6556fea2624855c193d0e3eTed KremenekQualType ArgTypeResult::getRepresentativeType(ASTContext &C) const {
3614e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  assert(isValid());
3624e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  if (K == SpecificTy)
3634e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    return T;
3644e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  if (K == CStrTy)
3654e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    return C.getPointerType(C.CharTy);
3664e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  if (K == WCStrTy)
36787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    return C.getPointerType(C.getWCharType());
3684e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  if (K == ObjCPointerTy)
3694e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek    return C.ObjCBuiltinIdTy;
3704e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3714e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  return QualType();
3724e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek}
3734e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3744e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
3754e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods on OptionalAmount.
3764e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
3774e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3784e4b30ec62d78b24e6556fea2624855c193d0e3eTed KremenekArgTypeResult OptionalAmount::getArgType(ASTContext &Ctx) const {
3794e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  return Ctx.IntTy;
3804e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek}
3814e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
3824e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
38333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek// Methods on FormatSpecifier.
38433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===//
38533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
38633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted KremenekArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const {
38733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (!CS.consumesDataArgument())
38833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    return ArgTypeResult::Invalid();
3894e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
39033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (CS.isIntArg())
39133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    switch (LM) {
3924e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      case AsLongDouble:
39333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult::Invalid();
39433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case None: return Ctx.IntTy;
39533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsChar: return Ctx.SignedCharTy;
39633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsShort: return Ctx.ShortTy;
39733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsLong: return Ctx.LongTy;
39833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsLongLong: return Ctx.LongLongTy;
39933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsIntMax:
40033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: Return unknown for now.
40133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
40233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsSizeT: return Ctx.getSizeType();
40333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsPtrDiff: return Ctx.getPointerDiffType();
40433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    }
40533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
40633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (CS.isUIntArg())
40733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    switch (LM) {
4084e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      case AsLongDouble:
40933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult::Invalid();
41033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case None: return Ctx.UnsignedIntTy;
41133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsChar: return Ctx.UnsignedCharTy;
41233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsShort: return Ctx.UnsignedShortTy;
41333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsLong: return Ctx.UnsignedLongTy;
41433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsLongLong: return Ctx.UnsignedLongLongTy;
41533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsIntMax:
41633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: Return unknown for now.
41733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
4184e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek      case AsSizeT:
41933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: How to get the corresponding unsigned
42033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // version of size_t?
42133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
42233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek      case AsPtrDiff:
42333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: How to get the corresponding unsigned
42433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // version of ptrdiff_t?
42533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
42633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    }
4274e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
428f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek  if (CS.isDoubleArg()) {
429f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek    if (LM == AsLongDouble)
430f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek      return Ctx.LongDoubleTy;
431c9a89fec60a20eb3269caa95eca048d45ab215adTed Kremenek    return Ctx.DoubleTy;
432f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek  }
43387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek
43487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek  switch (CS.getKind()) {
43587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case ConversionSpecifier::CStrArg:
43687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      return ArgTypeResult(LM == AsWideChar ? ArgTypeResult::WCStrTy                                            : ArgTypeResult::CStrTy);
43787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case ConversionSpecifier::UnicodeStrArg:
43887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      // FIXME: This appears to be Mac OS X specific.
43987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      return ArgTypeResult::WCStrTy;
44087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case ConversionSpecifier::CArg:
44187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      return Ctx.WCharTy;
44287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    default:
44387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      break;
44487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek  }
44587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek
44633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  // FIXME: Handle other cases.
44740888ada6022cfd4ab2a7c07ab276639860ffc5aTed Kremenek  return ArgTypeResult();
44833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek}
44933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
450