PrintfFormatString.cpp revision 826a3457f737f1fc45a22954fd1bfde38160c165
1826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//== PrintfFormatString.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
15826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek#include "clang/Analysis/Analyses/FormatString.h"
16826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek#include "FormatStringParsing.h"
178f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
18826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing clang::analyze_format_string::ArgTypeResult;
19826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing clang::analyze_format_string::FormatStringHandler;
20826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing clang::analyze_format_string::LengthModifier;
21826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing clang::analyze_format_string::OptionalAmount;
223bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Careusing clang::analyze_printf::ConversionSpecifier;
23826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing clang::analyze_printf::PrintfSpecifier;
24efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek
25808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenekusing namespace clang;
268f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
27826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenektypedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
28826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek        PrintfSpecifierResult;
294e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
304e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
314e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods for parsing format strings.
324e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
338f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
34826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing analyze_format_string::ParseNonPositionAmount;
35efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek
36826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekstatic bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
37efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek                           const char *Start, const char *&Beg, const char *E,
38efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek                           unsigned *argIndex) {
39efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (argIndex) {
40efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
41efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  }
42efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  else {
43efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
44826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                           analyze_format_string::PrecisionPos);
45efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    if (Amt.isInvalid())
46efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek      return true;
47efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    FS.setPrecision(Amt);
48efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  }
49efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  return false;
50efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek}
51efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek
52826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekstatic PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
5374d56a168966ff015824279a24aaf566180ed97dTed Kremenek                                                  const char *&Beg,
547f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek                                                  const char *E,
557f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek                                                  unsigned &argIndex) {
564e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
574b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenek  using namespace clang::analyze_printf;
584e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
598f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  const char *I = Beg;
60c7ae51a3cd9460db8280e8623c90614f246e46d2Ted Kremenek  const char *Start = 0;
618f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
628f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
638f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for a '%' character that indicates the start of a format specifier.
64e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek  for ( ; I != E ; ++I) {
658f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    char c = *I;
668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (c == '\0') {
678f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      // Detect spurious null characters, which are likely errors.
688f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      H.HandleNullChar(I);
698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
718f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (c == '%') {
72e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek      Start = I++;  // Record the start of the format specifier.
738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
764e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
778f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // No format specifier found?
788f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (!Start)
798f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return false;
804e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
818f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
828f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
83826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
848f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
858f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
864e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
87826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  PrintfSpecifier FS;
88efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (ParseArgPosition(H, FS, Start, I, E))
89efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    return true;
90efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek
91efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (I == E) {
92efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    // No more characters left?
93826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
94efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    return true;
95efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  }
964e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
978f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for flags (if any).
988f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  bool hasMore = true;
998f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  for ( ; I != E; ++I) {
1008f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    switch (*I) {
1018f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      default: hasMore = false; break;
102e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '-': FS.setIsLeftJustified(I); break;
103e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '+': FS.setHasPlusPrefix(I); break;
104e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case ' ': FS.setHasSpacePrefix(I); break;
105e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '#': FS.setHasAlternativeForm(I); break;
106e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '0': FS.setHasLeadingZeros(I); break;
1078f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1088f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (!hasMore)
1098f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
1104e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
1118f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1128f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1138f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
114826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1158f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1168f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1174e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1188f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for the field width (if any).
119efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (ParseFieldWidth(H, FS, Start, I, E,
120efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek                      FS.usesPositionalArg() ? 0 : &argIndex))
121efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    return true;
1224e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1248f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
125826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1268f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1274e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
1284e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1294e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  // Look for the precision (if any).
1308f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (*I == '.') {
131808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek    ++I;
1328f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (I == E) {
133826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      H.HandleIncompleteSpecifier(Start, E - Start);
1348f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
137efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    if (ParsePrecision(H, FS, Start, I, E,
138efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek                       FS.usesPositionalArg() ? 0 : &argIndex))
139efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek      return true;
1408f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1418f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (I == E) {
1428f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      // No more characters left?
143826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      H.HandleIncompleteSpecifier(Start, E - Start);
1448f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1478f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1488f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for the length modifier.
149826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  if (ParseLengthModifier(FS, I, E) && I == E) {
1508f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
151826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1538f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
154df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek
1554dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek  if (*I == '\0') {
156df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    // Detect spurious null characters, which are likely errors.
157df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    H.HandleNullChar(I);
158df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    return true;
1594dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek  }
1604e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1618f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Finally, look for the conversion specifier.
162a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  const char *conversionPosition = I++;
16326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
164a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  switch (*conversionPosition) {
1658f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    default:
16626ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek      break;
167c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek    // C99: 7.19.6.1 (section 8).
16887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case '%': k = ConversionSpecifier::PercentArg;   break;
16987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'A': k = ConversionSpecifier::AArg; break;
170a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'E': k = ConversionSpecifier::EArg; break;
17187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'F': k = ConversionSpecifier::FArg; break;
172a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'G': k = ConversionSpecifier::GArg; break;
17387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'X': k = ConversionSpecifier::XArg; break;
174a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'a': k = ConversionSpecifier::aArg; break;
175a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'c': k = ConversionSpecifier::IntAsCharArg; break;
17687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'd': k = ConversionSpecifier::dArg; break;
17787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'e': k = ConversionSpecifier::eArg; break;
17887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'f': k = ConversionSpecifier::fArg; break;
17987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'g': k = ConversionSpecifier::gArg; break;
18087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'i': k = ConversionSpecifier::iArg; break;
181a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'n': k = ConversionSpecifier::OutIntPtrArg; break;
18287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'o': k = ConversionSpecifier::oArg; break;
18387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'p': k = ConversionSpecifier::VoidPtrArg;   break;
18487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 's': k = ConversionSpecifier::CStrArg;      break;
18587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'u': k = ConversionSpecifier::uArg; break;
18687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'x': k = ConversionSpecifier::xArg; break;
18787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    // Mac OS X (unicode) specific
18887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'C': k = ConversionSpecifier::CArg; break;
18987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'S': k = ConversionSpecifier::UnicodeStrArg; break;
190c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek    // Objective-C.
1914dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek    case '@': k = ConversionSpecifier::ObjCObjArg; break;
192df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    // Glibc specific.
1934dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek    case 'm': k = ConversionSpecifier::PrintErrno; break;
1948f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1957f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek  ConversionSpecifier CS(conversionPosition, k);
1967f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek  FS.setConversionSpecifier(CS);
197efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
1987f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek    FS.setArgIndex(argIndex++);
19926ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek
20026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  if (k == ConversionSpecifier::InvalidSpecifier) {
2017f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek    // Assume the conversion takes one argument.
202826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return !H.HandleInvalidPrintfConversionSpecifier(FS, Beg, I - Beg);
20326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  }
204826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  return PrintfSpecifierResult(Start, FS);
2058f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
2068f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
207826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
208826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                                     const char *I,
209826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                                     const char *E) {
2107f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
2117f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek  unsigned argIndex = 0;
2127f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
2138f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Keep looking for a format specifier until we have exhausted the string.
2148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  while (I != E) {
215826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex);
21626ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // Did a fail-stop error of any kind occur when parsing the specifier?
21726ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // If so, don't do any more processing.
21826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    if (FSR.shouldStop())
2198f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;;
22026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // Did we exhaust the string or encounter an error that
22126ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // we can recover from?
2228f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (!FSR.hasValue())
22326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek      continue;
2248f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // We have a format specifier.  Pass it to the callback.
225826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
226a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek                                 I - FSR.getStart()))
2274dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek      return true;
2284e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
2294e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  assert(I == E && "Format string not exhausted");
2308f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  return false;
2318f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
2328f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
2334e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
2343bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care// Methods on ConversionSpecifier.
2353bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===//
2363bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Careconst char *ConversionSpecifier::toString() const {
2373bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  switch (kind) {
2383bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case dArg: return "d";
2393bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case iArg: return "i";
2403bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case oArg: return "o";
2413bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case uArg: return "u";
2423bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case xArg: return "x";
2433bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case XArg: return "X";
2443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case fArg: return "f";
2453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case FArg: return "F";
2463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case eArg: return "e";
2473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case EArg: return "E";
2483bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case gArg: return "g";
2493bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case GArg: return "G";
2503bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case aArg: return "a";
2513bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case AArg: return "A";
2523bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case IntAsCharArg:     return "c";
2533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case CStrArg:          return "s";
2543bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case VoidPtrArg:       return "p";
2553bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case OutIntPtrArg:     return "n";
2563bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case PercentArg:       return "%";
2573bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case InvalidSpecifier: return NULL;
2583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
2593bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // MacOS X unicode extensions.
2603bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case CArg:          return "C";
2613bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case UnicodeStrArg: return "S";
2623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
2633bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Objective-C specific specifiers.
2643bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case ObjCObjArg: return "@";
2653bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
2663bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // GlibC specific specifiers.
2673bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case PrintErrno: return "m";
2683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
2693bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  return NULL;
2703bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care}
2713bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
2723bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===//
273826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// Methods on PrintfSpecifier.
27433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===//
27533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
276826a3457f737f1fc45a22954fd1bfde38160c165Ted KremenekArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
27733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (!CS.consumesDataArgument())
27833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    return ArgTypeResult::Invalid();
2794e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
28033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (CS.isIntArg())
2813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    switch (LM.getKind()) {
2823bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongDouble:
28333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult::Invalid();
2843bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::None: return Ctx.IntTy;
2853bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsChar: return Ctx.SignedCharTy;
2863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsShort: return Ctx.ShortTy;
2873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLong: return Ctx.LongTy;
2883bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongLong: return Ctx.LongLongTy;
2893bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsIntMax:
29033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: Return unknown for now.
29133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
2923bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsSizeT: return Ctx.getSizeType();
2933bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsPtrDiff: return Ctx.getPointerDiffType();
29433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    }
29533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
29633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (CS.isUIntArg())
2973bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    switch (LM.getKind()) {
2983bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongDouble:
29933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult::Invalid();
3003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::None: return Ctx.UnsignedIntTy;
3013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
3023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
3033bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
3043bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy;
3053bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsIntMax:
30633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: Return unknown for now.
30733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
3083bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsSizeT:
30933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: How to get the corresponding unsigned
31033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // version of size_t?
31133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
3123bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsPtrDiff:
31333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: How to get the corresponding unsigned
31433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // version of ptrdiff_t?
31533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
31633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    }
3174e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
318f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek  if (CS.isDoubleArg()) {
3193bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    if (LM.getKind() == LengthModifier::AsLongDouble)
320f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek      return Ctx.LongDoubleTy;
321c9a89fec60a20eb3269caa95eca048d45ab215adTed Kremenek    return Ctx.DoubleTy;
322f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek  }
3237f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
32487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek  switch (CS.getKind()) {
32587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case ConversionSpecifier::CStrArg:
3263bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ?
3273bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care          ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy);
32887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case ConversionSpecifier::UnicodeStrArg:
32987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      // FIXME: This appears to be Mac OS X specific.
33087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      return ArgTypeResult::WCStrTy;
33187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case ConversionSpecifier::CArg:
3327f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek      return Ctx.WCharTy;
33313927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek    case ConversionSpecifier::VoidPtrArg:
33413927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek      return ArgTypeResult::CPointerTy;
33587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    default:
33687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      break;
33787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek  }
3387f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
33933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  // FIXME: Handle other cases.
34040888ada6022cfd4ab2a7c07ab276639860ffc5aTed Kremenek  return ArgTypeResult();
34133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek}
34233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
343826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::fixType(QualType QT) {
3443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Handle strings first (char *, wchar_t *)
3453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
3463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::CStrArg);
3473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
348876e994957472eda4b40136d4e1d6e08e2be338fTom Care    // Disable irrelevant flags
349876e994957472eda4b40136d4e1d6e08e2be338fTom Care    HasAlternativeForm = 0;
350876e994957472eda4b40136d4e1d6e08e2be338fTom Care    HasLeadingZeroes = 0;
351876e994957472eda4b40136d4e1d6e08e2be338fTom Care
3523bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    // Set the long length modifier for wide characters
3533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    if (QT->getPointeeType()->isWideCharType())
3543bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      LM.setKind(LengthModifier::AsWideChar);
3553bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
3563bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    return true;
3573bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
3583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
3593bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // We can only work with builtin types.
3603bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (!QT->isBuiltinType())
3613bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    return false;
3623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
3633bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Everything else should be a base type
3643bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  const BuiltinType *BT = QT->getAs<BuiltinType>();
365876e994957472eda4b40136d4e1d6e08e2be338fTom Care
3663bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Set length modifier
3673bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  switch (BT->getKind()) {
3683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  default:
369876e994957472eda4b40136d4e1d6e08e2be338fTom Care    // The rest of the conversions are either optional or for non-builtin types
370876e994957472eda4b40136d4e1d6e08e2be338fTom Care    LM.setKind(LengthModifier::None);
3713bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
372876e994957472eda4b40136d4e1d6e08e2be338fTom Care
3733bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::WChar:
3743bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::Long:
3753bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::ULong:
3763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLong);
3773bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
3783bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
3793bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::LongLong:
3803bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::ULongLong:
3813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLongLong);
3823bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
3833bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
3843bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::LongDouble:
3853bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLongDouble);
3863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
3873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
3883bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
3893bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Set conversion specifier and disable any flags which do not apply to it.
3903bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (QT->isAnyCharacterType()) {
3913bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::IntAsCharArg);
3923bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    Precision.setHowSpecified(OptionalAmount::NotSpecified);
3933bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
3943bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasLeadingZeroes = 0;
395e4ee9663168dfb2b4122c768091e30217328c9faTom Care    HasPlusPrefix = 0;
3963bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
3973bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
3980c293ea13d452c1a47a05ada5a5ee9acc69c66ccDouglas Gregor  else if (QT->isRealFloatingType()) {
3993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::fArg);
4003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  else if (QT->isPointerType()) {
4023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::VoidPtrArg);
4033bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    Precision.setHowSpecified(OptionalAmount::NotSpecified);
4043bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
4053bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasLeadingZeroes = 0;
406e4ee9663168dfb2b4122c768091e30217328c9faTom Care    HasPlusPrefix = 0;
4073bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4083bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  else if (QT->isSignedIntegerType()) {
4093bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::dArg);
4103bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
4113bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
412c8c4b4088cf0b3afeda425b25fa7c77d3873b12cDouglas Gregor  else if (QT->isUnsignedIntegerType()) {
4133bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::uArg);
4143bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
415e4ee9663168dfb2b4122c768091e30217328c9faTom Care    HasPlusPrefix = 0;
4163bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4173bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  else {
4183bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    return false;
4193bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4203bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4213bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  return true;
4223bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care}
4233bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
424826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekvoid PrintfSpecifier::toString(llvm::raw_ostream &os) const {
4253bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Whilst some features have no defined order, we are using the order
426826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) ¤7.19.6.1)
4273bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << "%";
4283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4293bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Positional args
4303bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (usesPositionalArg()) {
4313bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    os << getPositionalArgIndex() << "$";
4323bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4333bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4343bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Conversion flags
4353bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (IsLeftJustified)    os << "-";
4363bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasPlusPrefix)      os << "+";
4373bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasSpacePrefix)     os << " ";
4383bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasAlternativeForm) os << "#";
4393bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasLeadingZeroes)   os << "0";
4403bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4413bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Minimum field width
4423bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  FieldWidth.toString(os);
4433bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Precision
4443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  Precision.toString(os);
4453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Length modifier
4463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << LM.toString();
4473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Conversion specifier
4483bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << CS.toString();
4493bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care}
450e4ee9663168dfb2b4122c768091e30217328c9faTom Care
451826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidPlusPrefix() const {
452e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasPlusPrefix)
453e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
454e4ee9663168dfb2b4122c768091e30217328c9faTom Care
455e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The plus prefix only makes sense for signed conversions
456e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
457e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
458e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
459e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
460e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
461e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
462e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
463e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
464e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
465e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
466e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
467e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
468e4ee9663168dfb2b4122c768091e30217328c9faTom Care
469e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
470e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
471e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
472e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
473e4ee9663168dfb2b4122c768091e30217328c9faTom Care
474826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidAlternativeForm() const {
475e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasAlternativeForm)
476e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
477e4ee9663168dfb2b4122c768091e30217328c9faTom Care
478e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Alternate form flag only valid with the oxaAeEfFgG conversions
479e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
480e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
481e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
482e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
483e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
484e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
485e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
486e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
487e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
488e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
489e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
490e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
491e4ee9663168dfb2b4122c768091e30217328c9faTom Care
492e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
493e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
494e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
495e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
496e4ee9663168dfb2b4122c768091e30217328c9faTom Care
497826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidLeadingZeros() const {
498e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasLeadingZeroes)
499e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
500e4ee9663168dfb2b4122c768091e30217328c9faTom Care
501e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
502e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
503e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
504e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
505e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
506e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::uArg:
507e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
508e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::XArg:
509e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
510e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
511e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
512e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
513e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
514e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
515e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
516e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
517e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
518e4ee9663168dfb2b4122c768091e30217328c9faTom Care
519e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
520e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
521e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
522e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
523e4ee9663168dfb2b4122c768091e30217328c9faTom Care
524826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidSpacePrefix() const {
525e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasSpacePrefix)
526e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
527e4ee9663168dfb2b4122c768091e30217328c9faTom Care
528e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The space prefix only makes sense for signed conversions
529e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
530e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
531e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
532e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
533e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
534e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
535e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
536e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
537e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
538e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
539e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
540e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
541e4ee9663168dfb2b4122c768091e30217328c9faTom Care
542e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
543e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
544e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
545e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
546e4ee9663168dfb2b4122c768091e30217328c9faTom Care
547826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidLeftJustified() const {
548e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!IsLeftJustified)
549e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
550e4ee9663168dfb2b4122c768091e30217328c9faTom Care
551e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The left justified flag is valid for all conversions except n
552e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
553e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::OutIntPtrArg:
554e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
555e4ee9663168dfb2b4122c768091e30217328c9faTom Care
556e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
557e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
558e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
559e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
560e4ee9663168dfb2b4122c768091e30217328c9faTom Care
561826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidLengthModifier() const {
562e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (LM.getKind()) {
563e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case LengthModifier::None:
564e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
565e4ee9663168dfb2b4122c768091e30217328c9faTom Care
566e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Handle most integer flags
567e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case LengthModifier::AsChar:
568e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case LengthModifier::AsShort:
569e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case LengthModifier::AsLongLong:
570e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case LengthModifier::AsIntMax:
571e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case LengthModifier::AsSizeT:
572e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case LengthModifier::AsPtrDiff:
573e4ee9663168dfb2b4122c768091e30217328c9faTom Care    switch (CS.getKind()) {
574e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::dArg:
575e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::iArg:
576e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::oArg:
577e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::uArg:
578e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::xArg:
579e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::XArg:
580e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::OutIntPtrArg:
581e4ee9663168dfb2b4122c768091e30217328c9faTom Care      return true;
582e4ee9663168dfb2b4122c768091e30217328c9faTom Care    default:
583e4ee9663168dfb2b4122c768091e30217328c9faTom Care      return false;
584e4ee9663168dfb2b4122c768091e30217328c9faTom Care    }
585e4ee9663168dfb2b4122c768091e30217328c9faTom Care
586e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Handle 'l' flag
587e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case LengthModifier::AsLong:
588e4ee9663168dfb2b4122c768091e30217328c9faTom Care    switch (CS.getKind()) {
589e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::dArg:
590e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::iArg:
591e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::oArg:
592e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::uArg:
593e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::xArg:
594e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::XArg:
595e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::aArg:
596e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::AArg:
597e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::fArg:
598e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::FArg:
599e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::eArg:
600e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::EArg:
601e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::gArg:
602e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::GArg:
603e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::OutIntPtrArg:
604e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::IntAsCharArg:
605e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::CStrArg:
606e4ee9663168dfb2b4122c768091e30217328c9faTom Care      return true;
607e4ee9663168dfb2b4122c768091e30217328c9faTom Care    default:
608e4ee9663168dfb2b4122c768091e30217328c9faTom Care      return false;
609e4ee9663168dfb2b4122c768091e30217328c9faTom Care    }
610e4ee9663168dfb2b4122c768091e30217328c9faTom Care
611e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case LengthModifier::AsLongDouble:
612e4ee9663168dfb2b4122c768091e30217328c9faTom Care    switch (CS.getKind()) {
613e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::aArg:
614e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::AArg:
615e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::fArg:
616e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::FArg:
617e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::eArg:
618e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::EArg:
619e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::gArg:
620e4ee9663168dfb2b4122c768091e30217328c9faTom Care    case ConversionSpecifier::GArg:
621e4ee9663168dfb2b4122c768091e30217328c9faTom Care      return true;
622e4ee9663168dfb2b4122c768091e30217328c9faTom Care    default:
623e4ee9663168dfb2b4122c768091e30217328c9faTom Care      return false;
624e4ee9663168dfb2b4122c768091e30217328c9faTom Care    }
625e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
626e4ee9663168dfb2b4122c768091e30217328c9faTom Care  return false;
627e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
628e4ee9663168dfb2b4122c768091e30217328c9faTom Care
629826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidPrecision() const {
630e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
631e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
632e4ee9663168dfb2b4122c768091e30217328c9faTom Care
633e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Precision is only valid with the diouxXaAeEfFgGs conversions
634e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
635e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
636e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
637e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
638e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::uArg:
639e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
640e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::XArg:
641e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
642e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
643e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
644e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
645e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
646e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
647e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
648e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
649e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::CStrArg:
650e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
651e4ee9663168dfb2b4122c768091e30217328c9faTom Care
652e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
653e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
654e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
655e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
656826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidFieldWidth() const {
657e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
658e4ee9663168dfb2b4122c768091e30217328c9faTom Care      return true;
659e4ee9663168dfb2b4122c768091e30217328c9faTom Care
660e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The field width is valid for all conversions except n
661e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
662e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::OutIntPtrArg:
663e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
664e4ee9663168dfb2b4122c768091e30217328c9faTom Care
665e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
666e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
667e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
668e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
669