PrintfFormatString.cpp revision 117348caf0a8f91782e9e32e32a8689576f394d7
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;
226ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenekusing clang::analyze_format_string::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));
413060178ad9df29789505c1e6debcfc80a3a13587Chad Rosier  } else {
42efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
43826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                           analyze_format_string::PrecisionPos);
44efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    if (Amt.isInvalid())
45efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek      return true;
46efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    FS.setPrecision(Amt);
47efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  }
48efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  return false;
49efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek}
50efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek
51826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekstatic PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
5274d56a168966ff015824279a24aaf566180ed97dTed Kremenek                                                  const char *&Beg,
537f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek                                                  const char *E,
547f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek                                                  unsigned &argIndex) {
554e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
566ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  using namespace clang::analyze_format_string;
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;
102dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi      case '\'':
103bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek        // FIXME: POSIX specific.  Always accept?
104bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek        FS.setHasThousandsGrouping(I);
105bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek        break;
106e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '-': FS.setIsLeftJustified(I); break;
107e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '+': FS.setHasPlusPrefix(I); break;
108e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case ' ': FS.setHasSpacePrefix(I); break;
109e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '#': FS.setHasAlternativeForm(I); break;
110e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '0': FS.setHasLeadingZeros(I); break;
1118f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1128f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (!hasMore)
1138f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
1144e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
1158f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1168f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1178f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
118826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1198f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1208f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1214e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1228f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for the field width (if any).
123efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (ParseFieldWidth(H, FS, Start, I, E,
124efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek                      FS.usesPositionalArg() ? 0 : &argIndex))
125efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    return true;
1264e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1278f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1288f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
129826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1308f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1314e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
1324e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1334e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  // Look for the precision (if any).
1348f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (*I == '.') {
135808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek    ++I;
1368f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (I == E) {
137826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      H.HandleIncompleteSpecifier(Start, E - Start);
1388f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1404e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
141efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    if (ParsePrecision(H, FS, Start, I, E,
142efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek                       FS.usesPositionalArg() ? 0 : &argIndex))
143efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek      return true;
1448f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (I == E) {
1468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      // No more characters left?
147826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      H.HandleIncompleteSpecifier(Start, E - Start);
1488f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1508f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for the length modifier.
153826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  if (ParseLengthModifier(FS, I, E) && I == E) {
1548f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
155826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1568f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
158df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek
1594dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek  if (*I == '\0') {
160df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    // Detect spurious null characters, which are likely errors.
161df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    H.HandleNullChar(I);
162df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    return true;
1634dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek  }
1644e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1658f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Finally, look for the conversion specifier.
166a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  const char *conversionPosition = I++;
16726ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
168a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  switch (*conversionPosition) {
1698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    default:
17026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek      break;
171c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek    // C99: 7.19.6.1 (section 8).
17287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case '%': k = ConversionSpecifier::PercentArg;   break;
17387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'A': k = ConversionSpecifier::AArg; break;
174a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'E': k = ConversionSpecifier::EArg; break;
17587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'F': k = ConversionSpecifier::FArg; break;
176a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'G': k = ConversionSpecifier::GArg; break;
17787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'X': k = ConversionSpecifier::XArg; break;
178a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'a': k = ConversionSpecifier::aArg; break;
17992a6febe130dd9ad726983835297e11b2fa3b93fTed Kremenek    case 'c': k = ConversionSpecifier::cArg; break;
18087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'd': k = ConversionSpecifier::dArg; break;
18187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'e': k = ConversionSpecifier::eArg; break;
18287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'f': k = ConversionSpecifier::fArg; break;
18387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'g': k = ConversionSpecifier::gArg; break;
18487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'i': k = ConversionSpecifier::iArg; break;
18535d353b47bce29200b910371dd9b8ba7f3058ab8Ted Kremenek    case 'n': k = ConversionSpecifier::nArg; break;
18687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'o': k = ConversionSpecifier::oArg; break;
18766932056da99d2441e27c10b27c82706671e1dbfTed Kremenek    case 'p': k = ConversionSpecifier::pArg;   break;
18899196b1031d37d37f395a3291ccdd12a3fc01242Ted Kremenek    case 's': k = ConversionSpecifier::sArg;      break;
18987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'u': k = ConversionSpecifier::uArg; break;
19087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'x': k = ConversionSpecifier::xArg; break;
191bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek    // POSIX specific.
19287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'C': k = ConversionSpecifier::CArg; break;
193de183a48dd8fcff5e0343e84c8a6b563088447ceTed Kremenek    case 'S': k = ConversionSpecifier::SArg; break;
194c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek    // Objective-C.
1954dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek    case '@': k = ConversionSpecifier::ObjCObjArg; break;
196df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    // Glibc specific.
1974dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek    case 'm': k = ConversionSpecifier::PrintErrno; break;
1988f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1996ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  PrintfConversionSpecifier CS(conversionPosition, k);
2007f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek  FS.setConversionSpecifier(CS);
201efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
2027f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek    FS.setArgIndex(argIndex++);
20326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek
20426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  if (k == ConversionSpecifier::InvalidSpecifier) {
2057f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek    // Assume the conversion takes one argument.
2067966297a70996977f167a8676568f02f4283bdd6Ted Kremenek    return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
20726ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  }
208826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  return PrintfSpecifierResult(Start, FS);
2098f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
2108f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
211826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
212826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                                     const char *I,
213826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                                     const char *E) {
2147f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
2157f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek  unsigned argIndex = 0;
2167f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
2178f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Keep looking for a format specifier until we have exhausted the string.
2188f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  while (I != E) {
219826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex);
22026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // Did a fail-stop error of any kind occur when parsing the specifier?
22126ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // If so, don't do any more processing.
22226ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    if (FSR.shouldStop())
2238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;;
22426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // Did we exhaust the string or encounter an error that
22526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // we can recover from?
2268f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (!FSR.hasValue())
22726ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek      continue;
2288f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // We have a format specifier.  Pass it to the callback.
229826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
230a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek                                 I - FSR.getStart()))
2314dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek      return true;
2324e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
2334e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  assert(I == E && "Format string not exhausted");
2348f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  return false;
2358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
2368f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
2374e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
2383bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care// Methods on ConversionSpecifier.
2393bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===//
2403bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Careconst char *ConversionSpecifier::toString() const {
2413bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  switch (kind) {
2423bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case dArg: return "d";
2433bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case iArg: return "i";
2443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case oArg: return "o";
2453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case uArg: return "u";
2463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case xArg: return "x";
2473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case XArg: return "X";
2483bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case fArg: return "f";
2493bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case FArg: return "F";
2503bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case eArg: return "e";
2513bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case EArg: return "E";
2523bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case gArg: return "g";
2533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case GArg: return "G";
2543bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case aArg: return "a";
2553bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case AArg: return "A";
2567fdba13847f01cfcdc7c9261b13e99e3cbecb5fcTed Kremenek  case cArg: return "c";
2577fdba13847f01cfcdc7c9261b13e99e3cbecb5fcTed Kremenek  case sArg: return "s";
2587fdba13847f01cfcdc7c9261b13e99e3cbecb5fcTed Kremenek  case pArg: return "p";
2597fdba13847f01cfcdc7c9261b13e99e3cbecb5fcTed Kremenek  case nArg: return "n";
2607fdba13847f01cfcdc7c9261b13e99e3cbecb5fcTed Kremenek  case PercentArg:  return "%";
2617fdba13847f01cfcdc7c9261b13e99e3cbecb5fcTed Kremenek  case ScanListArg: return "[";
2623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case InvalidSpecifier: return NULL;
2633bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
2643bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // MacOS X unicode extensions.
2657fdba13847f01cfcdc7c9261b13e99e3cbecb5fcTed Kremenek  case CArg: return "C";
266de183a48dd8fcff5e0343e84c8a6b563088447ceTed Kremenek  case SArg: return "S";
2673bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
2683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Objective-C specific specifiers.
2693bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case ObjCObjArg: return "@";
2703bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
2713bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // GlibC specific specifiers.
2723bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case PrintErrno: return "m";
2733bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
2743bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  return NULL;
2753bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care}
2763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
2773bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===//
278826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// Methods on PrintfSpecifier.
27933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===//
28033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
281687b5df89d4ba91219df578d02087c68c09a0332Nick LewyckyArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
2826ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  const PrintfConversionSpecifier &CS = getConversionSpecifier();
283dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi
28433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (!CS.consumesDataArgument())
28533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    return ArgTypeResult::Invalid();
2864e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
2879325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek  if (CS.getKind() == ConversionSpecifier::cArg)
2889325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek    switch (LM.getKind()) {
2899325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek      case LengthModifier::None: return Ctx.IntTy;
2909325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek      case LengthModifier::AsLong: return ArgTypeResult::WIntTy;
2919325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek      default:
2929325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek        return ArgTypeResult::Invalid();
2939325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek    }
294dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi
29533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (CS.isIntArg())
2963bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    switch (LM.getKind()) {
2973bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongDouble:
29833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult::Invalid();
2993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::None: return Ctx.IntTy;
3006ca4a9ae99d65948e578d3e7d1f58ab6a947d2d7Ted Kremenek      case LengthModifier::AsChar: return ArgTypeResult::AnyCharTy;
3013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsShort: return Ctx.ShortTy;
3023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLong: return Ctx.LongTy;
3033bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongLong: return Ctx.LongLongTy;
304a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg      case LengthModifier::AsIntMax:
305a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg        return ArgTypeResult(Ctx.getIntMaxType(), "intmax_t");
30629e97cb35fab314388f62b68fefa78947e93c1dcHans Wennborg      case LengthModifier::AsSizeT:
30729e97cb35fab314388f62b68fefa78947e93c1dcHans Wennborg        // FIXME: How to get the corresponding signed version of size_t?
30833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
309a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg      case LengthModifier::AsPtrDiff:
310a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg        return ArgTypeResult(Ctx.getPointerDiffType(), "ptrdiff_t");
31133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    }
31233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
31333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (CS.isUIntArg())
3143bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    switch (LM.getKind()) {
3153bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongDouble:
31633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult::Invalid();
3173bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::None: return Ctx.UnsignedIntTy;
3183bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
3193bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
3203bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
3213bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy;
322a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg      case LengthModifier::AsIntMax:
323a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg        return ArgTypeResult(Ctx.getUIntMaxType(), "uintmax_t");
3243bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsSizeT:
325a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg        return ArgTypeResult(Ctx.getSizeType(), "size_t");
3263bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsPtrDiff:
32733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: How to get the corresponding unsigned
32833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // version of ptrdiff_t?
32933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
33033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    }
3314e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
332f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek  if (CS.isDoubleArg()) {
3333bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    if (LM.getKind() == LengthModifier::AsLongDouble)
334f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek      return Ctx.LongDoubleTy;
335c9a89fec60a20eb3269caa95eca048d45ab215adTed Kremenek    return Ctx.DoubleTy;
336f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek  }
3377f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
33887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek  switch (CS.getKind()) {
33999196b1031d37d37f395a3291ccdd12a3fc01242Ted Kremenek    case ConversionSpecifier::sArg:
3403bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ?
3413bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care          ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy);
342de183a48dd8fcff5e0343e84c8a6b563088447ceTed Kremenek    case ConversionSpecifier::SArg:
34387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      // FIXME: This appears to be Mac OS X specific.
34487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      return ArgTypeResult::WCStrTy;
34587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case ConversionSpecifier::CArg:
3467f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek      return Ctx.WCharTy;
34766932056da99d2441e27c10b27c82706671e1dbfTed Kremenek    case ConversionSpecifier::pArg:
34813927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek      return ArgTypeResult::CPointerTy;
34987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    default:
35087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      break;
35187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek  }
3527f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
35333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  // FIXME: Handle other cases.
35440888ada6022cfd4ab2a7c07ab276639860ffc5aTed Kremenek  return ArgTypeResult();
35533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek}
35633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
357a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborgbool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt) {
3583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Handle strings first (char *, wchar_t *)
3593bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
36099196b1031d37d37f395a3291ccdd12a3fc01242Ted Kremenek    CS.setKind(ConversionSpecifier::sArg);
3613bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
362876e994957472eda4b40136d4e1d6e08e2be338fTom Care    // Disable irrelevant flags
363876e994957472eda4b40136d4e1d6e08e2be338fTom Care    HasAlternativeForm = 0;
364876e994957472eda4b40136d4e1d6e08e2be338fTom Care    HasLeadingZeroes = 0;
365876e994957472eda4b40136d4e1d6e08e2be338fTom Care
3663bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    // Set the long length modifier for wide characters
3673bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    if (QT->getPointeeType()->isWideCharType())
3683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      LM.setKind(LengthModifier::AsWideChar);
369117348caf0a8f91782e9e32e32a8689576f394d7Hans Wennborg    else
370117348caf0a8f91782e9e32e32a8689576f394d7Hans Wennborg      LM.setKind(LengthModifier::None);
3713bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
3723bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    return true;
3733bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
3743bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
3753bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // We can only work with builtin types.
3763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  const BuiltinType *BT = QT->getAs<BuiltinType>();
3772dde35bc626153492f5f58202506c88a27fbff5bJohn McCall  if (!BT)
3782dde35bc626153492f5f58202506c88a27fbff5bJohn McCall    return false;
379876e994957472eda4b40136d4e1d6e08e2be338fTom Care
3803bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Set length modifier
3813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  switch (BT->getKind()) {
38206d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Bool:
38306d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::WChar_U:
38406d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::WChar_S:
38506d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Char16:
38606d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Char32:
38706d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::UInt128:
38806d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Int128:
389aa4a99b4a62615db243f7a5c433169f2fc704420Anton Korobeynikov  case BuiltinType::Half:
3902dde35bc626153492f5f58202506c88a27fbff5bJohn McCall    // Various types which are non-trivial to correct.
39106d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman    return false;
39206d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman
3932dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define SIGNED_TYPE(Id, SingletonId)
3942dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define UNSIGNED_TYPE(Id, SingletonId)
3952dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define FLOATING_TYPE(Id, SingletonId)
3962dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define BUILTIN_TYPE(Id, SingletonId) \
3972dde35bc626153492f5f58202506c88a27fbff5bJohn McCall  case BuiltinType::Id:
3982dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#include "clang/AST/BuiltinTypes.def"
39906d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman    // Misc other stuff which doesn't make sense here.
40006d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman    return false;
40106d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman
40206d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::UInt:
40306d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Int:
40406d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Float:
40506d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Double:
406876e994957472eda4b40136d4e1d6e08e2be338fTom Care    LM.setKind(LengthModifier::None);
4073bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
408876e994957472eda4b40136d4e1d6e08e2be338fTom Care
4094d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::Char_U:
4104d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::UChar:
4114d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::Char_S:
4124d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::SChar:
4134d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    LM.setKind(LengthModifier::AsChar);
4144d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    break;
4154d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek
4164d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::Short:
4174d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::UShort:
4184d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    LM.setKind(LengthModifier::AsShort);
4194d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    break;
4204d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek
4213bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::Long:
4223bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::ULong:
4233bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLong);
4243bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
4253bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4263bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::LongLong:
4273bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::ULongLong:
4283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLongLong);
4293bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
4303bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4313bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::LongDouble:
4323bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLongDouble);
4333bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
4343bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4353bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
436a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
437a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) {
438a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg    const IdentifierInfo *Identifier = QT.getBaseTypeIdentifier();
439a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg    if (Identifier->getName() == "size_t") {
440a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg      LM.setKind(LengthModifier::AsSizeT);
441a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg    } else if (Identifier->getName() == "ssize_t") {
442a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg      // Not C99, but common in Unix.
443a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg      LM.setKind(LengthModifier::AsSizeT);
444a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg    } else if (Identifier->getName() == "intmax_t") {
445a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg      LM.setKind(LengthModifier::AsIntMax);
446a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg    } else if (Identifier->getName() == "uintmax_t") {
447a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg      LM.setKind(LengthModifier::AsIntMax);
448a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg    } else if (Identifier->getName() == "ptrdiff_t") {
449a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg      LM.setKind(LengthModifier::AsPtrDiff);
450a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg    }
451a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg  }
452a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg
4533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Set conversion specifier and disable any flags which do not apply to it.
4544d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
4554d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) {
45692a6febe130dd9ad726983835297e11b2fa3b93fTed Kremenek    CS.setKind(ConversionSpecifier::cArg);
4574d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    LM.setKind(LengthModifier::None);
4583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    Precision.setHowSpecified(OptionalAmount::NotSpecified);
4593bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
4603bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasLeadingZeroes = 0;
461e4ee9663168dfb2b4122c768091e30217328c9faTom Care    HasPlusPrefix = 0;
4623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4633bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
4640c293ea13d452c1a47a05ada5a5ee9acc69c66ccDouglas Gregor  else if (QT->isRealFloatingType()) {
4653bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::fArg);
4663bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4673bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  else if (QT->isSignedIntegerType()) {
4683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::dArg);
4693bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
4703bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
471c8c4b4088cf0b3afeda425b25fa7c77d3873b12cDouglas Gregor  else if (QT->isUnsignedIntegerType()) {
4721e713f50e904b96623425efa7119fcb98243e111Ted Kremenek    // Preserve the original formatting, e.g. 'X', 'o'.
4731e713f50e904b96623425efa7119fcb98243e111Ted Kremenek    if (!cast<PrintfConversionSpecifier>(CS).isUIntArg())
4741e713f50e904b96623425efa7119fcb98243e111Ted Kremenek      CS.setKind(ConversionSpecifier::uArg);
4753bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
476e4ee9663168dfb2b4122c768091e30217328c9faTom Care    HasPlusPrefix = 0;
4773060178ad9df29789505c1e6debcfc80a3a13587Chad Rosier  } else {
478b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie    llvm_unreachable("Unexpected type");
4793bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4803bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  return true;
4823bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care}
4833bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4845f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid PrintfSpecifier::toString(raw_ostream &os) const {
4853bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Whilst some features have no defined order, we are using the order
4860099530a2288df7c2140dd8992b7310b9f6930a9NAKAMURA Takumi  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
4873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << "%";
4883bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4893bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Positional args
4903bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (usesPositionalArg()) {
4913bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    os << getPositionalArgIndex() << "$";
4923bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4933bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4943bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Conversion flags
4953bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (IsLeftJustified)    os << "-";
4963bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasPlusPrefix)      os << "+";
4973bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasSpacePrefix)     os << " ";
4983bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasAlternativeForm) os << "#";
4993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasLeadingZeroes)   os << "0";
5003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
5013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Minimum field width
5023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  FieldWidth.toString(os);
5033bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Precision
5043bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  Precision.toString(os);
5053bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Length modifier
5063bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << LM.toString();
5073bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Conversion specifier
5083bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << CS.toString();
5093bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care}
510e4ee9663168dfb2b4122c768091e30217328c9faTom Care
511826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidPlusPrefix() const {
512e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasPlusPrefix)
513e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
514e4ee9663168dfb2b4122c768091e30217328c9faTom Care
515e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The plus prefix only makes sense for signed conversions
516e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
517e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
518e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
519e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
520e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
521e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
522e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
523e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
524e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
525e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
526e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
527e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
528e4ee9663168dfb2b4122c768091e30217328c9faTom Care
529e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
530e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
531e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
532e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
533e4ee9663168dfb2b4122c768091e30217328c9faTom Care
534826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidAlternativeForm() const {
535e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasAlternativeForm)
536e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
537e4ee9663168dfb2b4122c768091e30217328c9faTom Care
5382e6c19abcf97c25f4d7458a9db89c5ab0158717dAnders Carlsson  // Alternate form flag only valid with the oxXaAeEfFgG conversions
539e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
540e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
541e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
5422e6c19abcf97c25f4d7458a9db89c5ab0158717dAnders Carlsson  case ConversionSpecifier::XArg:
543e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
544e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
545e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
546e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
547e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
548e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
549e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
550e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
551e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
552e4ee9663168dfb2b4122c768091e30217328c9faTom Care
553e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
554e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
555e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
556e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
557e4ee9663168dfb2b4122c768091e30217328c9faTom Care
558826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidLeadingZeros() const {
559e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasLeadingZeroes)
560e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
561e4ee9663168dfb2b4122c768091e30217328c9faTom Care
562e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
563e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
564e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
565e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
566e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
567e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::uArg:
568e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
569e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::XArg:
570e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
571e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
572e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
573e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
574e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
575e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
576e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
577e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
578e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
579e4ee9663168dfb2b4122c768091e30217328c9faTom Care
580e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
581e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
582e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
583e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
584e4ee9663168dfb2b4122c768091e30217328c9faTom Care
585826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidSpacePrefix() const {
586e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasSpacePrefix)
587e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
588e4ee9663168dfb2b4122c768091e30217328c9faTom Care
589e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The space prefix only makes sense for signed conversions
590e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
591e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
592e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
593e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
594e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
595e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
596e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
597e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
598e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
599e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
600e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
601e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
602e4ee9663168dfb2b4122c768091e30217328c9faTom Care
603e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
604e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
605e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
606e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
607e4ee9663168dfb2b4122c768091e30217328c9faTom Care
608826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidLeftJustified() const {
609e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!IsLeftJustified)
610e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
611e4ee9663168dfb2b4122c768091e30217328c9faTom Care
612e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The left justified flag is valid for all conversions except n
613e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
61435d353b47bce29200b910371dd9b8ba7f3058ab8Ted Kremenek  case ConversionSpecifier::nArg:
615e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
616e4ee9663168dfb2b4122c768091e30217328c9faTom Care
617e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
618e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
619e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
620e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
621e4ee9663168dfb2b4122c768091e30217328c9faTom Care
62265197b4b0c55bb74af0450230d61ee9461223721Ted Kremenekbool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
62365197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  if (!HasThousandsGrouping)
62465197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    return true;
625dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi
62665197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  switch (CS.getKind()) {
62765197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::dArg:
62865197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::iArg:
62965197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::uArg:
63065197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::fArg:
63165197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::FArg:
63265197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::gArg:
63365197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::GArg:
63465197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek      return true;
63565197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    default:
63665197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek      return false;
63765197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  }
63865197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek}
63965197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek
640826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidPrecision() const {
641e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
642e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
643e4ee9663168dfb2b4122c768091e30217328c9faTom Care
644e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Precision is only valid with the diouxXaAeEfFgGs conversions
645e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
646e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
647e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
648e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
649e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::uArg:
650e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
651e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::XArg:
652e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
653e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
654e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
655e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
656e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
657e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
658e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
659e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
66099196b1031d37d37f395a3291ccdd12a3fc01242Ted Kremenek  case ConversionSpecifier::sArg:
661e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
662e4ee9663168dfb2b4122c768091e30217328c9faTom Care
663e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
664e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
665e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
666e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
667826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidFieldWidth() const {
668e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
669e4ee9663168dfb2b4122c768091e30217328c9faTom Care      return true;
670e4ee9663168dfb2b4122c768091e30217328c9faTom Care
671e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The field width is valid for all conversions except n
672e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
67335d353b47bce29200b910371dd9b8ba7f3058ab8Ted Kremenek  case ConversionSpecifier::nArg:
674e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
675e4ee9663168dfb2b4122c768091e30217328c9faTom Care
676e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
677e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
678e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
679e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
680