PrintfFormatString.cpp revision cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9
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,
54d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg                                                  unsigned &argIndex,
55d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg                                                  const LangOptions &LO) {
564e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
576ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  using namespace clang::analyze_format_string;
584b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenek  using namespace clang::analyze_printf;
594e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
608f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  const char *I = Beg;
61c7ae51a3cd9460db8280e8623c90614f246e46d2Ted Kremenek  const char *Start = 0;
628f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
638f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
648f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for a '%' character that indicates the start of a format specifier.
65e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek  for ( ; I != E ; ++I) {
668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    char c = *I;
678f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (c == '\0') {
688f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      // Detect spurious null characters, which are likely errors.
698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      H.HandleNullChar(I);
708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
718f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
728f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (c == '%') {
73e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek      Start = I++;  // Record the start of the format specifier.
748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
768f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
774e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
788f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // No format specifier found?
798f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (!Start)
808f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return false;
814e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
828f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
838f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
84826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
858f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
868f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
874e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
88826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  PrintfSpecifier FS;
89efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (ParseArgPosition(H, FS, Start, I, E))
90efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    return true;
91efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek
92efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (I == E) {
93efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    // No more characters left?
94826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
95efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    return true;
96efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  }
974e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
988f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for flags (if any).
998f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  bool hasMore = true;
1008f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  for ( ; I != E; ++I) {
1018f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    switch (*I) {
1028f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      default: hasMore = false; break;
103dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi      case '\'':
104bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek        // FIXME: POSIX specific.  Always accept?
105bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek        FS.setHasThousandsGrouping(I);
106bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek        break;
107e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '-': FS.setIsLeftJustified(I); break;
108e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '+': FS.setHasPlusPrefix(I); break;
109e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case ' ': FS.setHasSpacePrefix(I); break;
110e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '#': FS.setHasAlternativeForm(I); break;
111e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '0': FS.setHasLeadingZeros(I); break;
1128f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1138f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (!hasMore)
1148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
1154e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
1168f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1178f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1188f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
119826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1208f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1218f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1224e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for the field width (if any).
124efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (ParseFieldWidth(H, FS, Start, I, E,
125efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek                      FS.usesPositionalArg() ? 0 : &argIndex))
126efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    return true;
1274e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1288f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1298f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
130826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1318f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1324e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
1334e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1344e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  // Look for the precision (if any).
1358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (*I == '.') {
136808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek    ++I;
1378f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (I == E) {
138826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      H.HandleIncompleteSpecifier(Start, E - Start);
1398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1408f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1414e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
142efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    if (ParsePrecision(H, FS, Start, I, E,
143efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek                       FS.usesPositionalArg() ? 0 : &argIndex))
144efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek      return true;
1458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (I == E) {
1478f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      // No more characters left?
148826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      H.HandleIncompleteSpecifier(Start, E - Start);
1498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1508f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1538f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for the length modifier.
154d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg  if (ParseLengthModifier(FS, I, E, LO) && I == E) {
1558f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
156826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1588f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
159df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek
1604dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek  if (*I == '\0') {
161df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    // Detect spurious null characters, which are likely errors.
162df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    H.HandleNullChar(I);
163df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    return true;
1644dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek  }
1654e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Finally, look for the conversion specifier.
167a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  const char *conversionPosition = I++;
16826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
169a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  switch (*conversionPosition) {
1708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    default:
17126ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek      break;
172c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek    // C99: 7.19.6.1 (section 8).
17387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case '%': k = ConversionSpecifier::PercentArg;   break;
17487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'A': k = ConversionSpecifier::AArg; break;
175a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'E': k = ConversionSpecifier::EArg; break;
17687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'F': k = ConversionSpecifier::FArg; break;
177a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'G': k = ConversionSpecifier::GArg; break;
17887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'X': k = ConversionSpecifier::XArg; break;
179a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'a': k = ConversionSpecifier::aArg; break;
18092a6febe130dd9ad726983835297e11b2fa3b93fTed Kremenek    case 'c': k = ConversionSpecifier::cArg; break;
18187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'd': k = ConversionSpecifier::dArg; break;
18287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'e': k = ConversionSpecifier::eArg; break;
18387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'f': k = ConversionSpecifier::fArg; break;
18487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'g': k = ConversionSpecifier::gArg; break;
18587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'i': k = ConversionSpecifier::iArg; break;
18635d353b47bce29200b910371dd9b8ba7f3058ab8Ted Kremenek    case 'n': k = ConversionSpecifier::nArg; break;
18787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'o': k = ConversionSpecifier::oArg; break;
18866932056da99d2441e27c10b27c82706671e1dbfTed Kremenek    case 'p': k = ConversionSpecifier::pArg;   break;
18999196b1031d37d37f395a3291ccdd12a3fc01242Ted Kremenek    case 's': k = ConversionSpecifier::sArg;      break;
19087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'u': k = ConversionSpecifier::uArg; break;
19187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'x': k = ConversionSpecifier::xArg; break;
192bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek    // POSIX specific.
19387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'C': k = ConversionSpecifier::CArg; break;
194de183a48dd8fcff5e0343e84c8a6b563088447ceTed Kremenek    case 'S': k = ConversionSpecifier::SArg; break;
195c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek    // Objective-C.
1964dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek    case '@': k = ConversionSpecifier::ObjCObjArg; break;
197df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    // Glibc specific.
1984dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek    case 'm': k = ConversionSpecifier::PrintErrno; break;
1998f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
2006ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  PrintfConversionSpecifier CS(conversionPosition, k);
2017f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek  FS.setConversionSpecifier(CS);
202efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
2037f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek    FS.setArgIndex(argIndex++);
20426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek
20526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  if (k == ConversionSpecifier::InvalidSpecifier) {
2067f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek    // Assume the conversion takes one argument.
2077966297a70996977f167a8676568f02f4283bdd6Ted Kremenek    return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
20826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  }
209826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  return PrintfSpecifierResult(Start, FS);
2108f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
2118f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
212826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
213826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                                     const char *I,
214d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg                                                     const char *E,
215d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg                                                     const LangOptions &LO) {
2167f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
2177f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek  unsigned argIndex = 0;
2187f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
2198f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Keep looking for a format specifier until we have exhausted the string.
2208f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  while (I != E) {
221d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
222d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg                                                            LO);
22326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // Did a fail-stop error of any kind occur when parsing the specifier?
22426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // If so, don't do any more processing.
22526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    if (FSR.shouldStop())
2268f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;;
22726ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // Did we exhaust the string or encounter an error that
22826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // we can recover from?
2298f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (!FSR.hasValue())
23026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek      continue;
2318f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // We have a format specifier.  Pass it to the callback.
232826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
233a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek                                 I - FSR.getStart()))
2344dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek      return true;
2354e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
2364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  assert(I == E && "Format string not exhausted");
2378f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  return false;
2388f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
2398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
2404e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
241826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// Methods on PrintfSpecifier.
24233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===//
24333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
244339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico WeberArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx,
245339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber                                          bool IsObjCLiteral) const {
2466ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  const PrintfConversionSpecifier &CS = getConversionSpecifier();
247dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi
24833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (!CS.consumesDataArgument())
24933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    return ArgTypeResult::Invalid();
2504e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
2519325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek  if (CS.getKind() == ConversionSpecifier::cArg)
2529325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek    switch (LM.getKind()) {
2539325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek      case LengthModifier::None: return Ctx.IntTy;
254f4f0c6095d1f481b94c6821c65e3bf1c9df42af7Hans Wennborg      case LengthModifier::AsLong:
255f4f0c6095d1f481b94c6821c65e3bf1c9df42af7Hans Wennborg        return ArgTypeResult(ArgTypeResult::WIntTy, "wint_t");
2569325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek      default:
2579325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek        return ArgTypeResult::Invalid();
2589325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek    }
259dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi
26033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (CS.isIntArg())
2613bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    switch (LM.getKind()) {
2623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongDouble:
2639d24c2cbd9cf1b7c165ccb13221f2efb2f4b49b0Ted Kremenek        // GNU extension.
2649d24c2cbd9cf1b7c165ccb13221f2efb2f4b49b0Ted Kremenek        return Ctx.LongLongTy;
2653bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::None: return Ctx.IntTy;
2666ca4a9ae99d65948e578d3e7d1f58ab6a947d2d7Ted Kremenek      case LengthModifier::AsChar: return ArgTypeResult::AnyCharTy;
2673bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsShort: return Ctx.ShortTy;
2683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLong: return Ctx.LongTy;
26932addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg      case LengthModifier::AsLongLong:
27032addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg      case LengthModifier::AsQuad:
27132addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg        return Ctx.LongLongTy;
272a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg      case LengthModifier::AsIntMax:
273a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg        return ArgTypeResult(Ctx.getIntMaxType(), "intmax_t");
27429e97cb35fab314388f62b68fefa78947e93c1dcHans Wennborg      case LengthModifier::AsSizeT:
27529e97cb35fab314388f62b68fefa78947e93c1dcHans Wennborg        // FIXME: How to get the corresponding signed version of size_t?
27633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
277a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg      case LengthModifier::AsPtrDiff:
278a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg        return ArgTypeResult(Ctx.getPointerDiffType(), "ptrdiff_t");
279d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg      case LengthModifier::AsAllocate:
28037969b7e14d6a4dfd934ef6d3738cc90b832ec1dHans Wennborg      case LengthModifier::AsMAllocate:
281d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg        return ArgTypeResult::Invalid();
28233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    }
28333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
28433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (CS.isUIntArg())
2853bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    switch (LM.getKind()) {
2863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongDouble:
2879d24c2cbd9cf1b7c165ccb13221f2efb2f4b49b0Ted Kremenek        // GNU extension.
2889d24c2cbd9cf1b7c165ccb13221f2efb2f4b49b0Ted Kremenek        return Ctx.UnsignedLongLongTy;
2893bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::None: return Ctx.UnsignedIntTy;
2903bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
2913bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
2923bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
29332addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg      case LengthModifier::AsLongLong:
29432addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg      case LengthModifier::AsQuad:
29532addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg        return Ctx.UnsignedLongLongTy;
296a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg      case LengthModifier::AsIntMax:
297a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg        return ArgTypeResult(Ctx.getUIntMaxType(), "uintmax_t");
2983bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsSizeT:
299a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg        return ArgTypeResult(Ctx.getSizeType(), "size_t");
3003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsPtrDiff:
30133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: How to get the corresponding unsigned
30233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // version of ptrdiff_t?
30333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        return ArgTypeResult();
304d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg      case LengthModifier::AsAllocate:
30537969b7e14d6a4dfd934ef6d3738cc90b832ec1dHans Wennborg      case LengthModifier::AsMAllocate:
306d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg        return ArgTypeResult::Invalid();
30733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    }
3084e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
309f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek  if (CS.isDoubleArg()) {
3103bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    if (LM.getKind() == LengthModifier::AsLongDouble)
311f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek      return Ctx.LongDoubleTy;
312c9a89fec60a20eb3269caa95eca048d45ab215adTed Kremenek    return Ctx.DoubleTy;
313f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek  }
3147f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
31587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek  switch (CS.getKind()) {
316630821869c4ec4604ab479d66e5ff81147a858e1Hans Wennborg    case ConversionSpecifier::sArg:
317339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber      if (LM.getKind() == LengthModifier::AsWideChar) {
318339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber        if (IsObjCLiteral)
319339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber          return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst());
320f4f0c6095d1f481b94c6821c65e3bf1c9df42af7Hans Wennborg        return ArgTypeResult(ArgTypeResult::WCStrTy, "wchar_t *");
321339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber      }
322f4f0c6095d1f481b94c6821c65e3bf1c9df42af7Hans Wennborg      return ArgTypeResult::CStrTy;
323de183a48dd8fcff5e0343e84c8a6b563088447ceTed Kremenek    case ConversionSpecifier::SArg:
324339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber      if (IsObjCLiteral)
325339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber        return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst());
326f4f0c6095d1f481b94c6821c65e3bf1c9df42af7Hans Wennborg      return ArgTypeResult(ArgTypeResult::WCStrTy, "wchar_t *");
32787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case ConversionSpecifier::CArg:
328339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber      if (IsObjCLiteral)
329339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber        return Ctx.UnsignedShortTy;
330f4f0c6095d1f481b94c6821c65e3bf1c9df42af7Hans Wennborg      return ArgTypeResult(Ctx.WCharTy, "wchar_t");
33166932056da99d2441e27c10b27c82706671e1dbfTed Kremenek    case ConversionSpecifier::pArg:
33213927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek      return ArgTypeResult::CPointerTy;
333cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9Hans Wennborg    case ConversionSpecifier::nArg:
334cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9Hans Wennborg      return Ctx.getPointerType(Ctx.IntTy);
335e6ca97f2aeb301e28d20988b27c4297a9b540991Ted Kremenek    case ConversionSpecifier::ObjCObjArg:
336e6ca97f2aeb301e28d20988b27c4297a9b540991Ted Kremenek      return ArgTypeResult::ObjCPointerTy;
33787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    default:
33887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      break;
33987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek  }
3407f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
34133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  // FIXME: Handle other cases.
34240888ada6022cfd4ab2a7c07ab276639860ffc5aTed Kremenek  return ArgTypeResult();
34333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek}
34433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
345be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborgbool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
346be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg                              ASTContext &Ctx, bool IsObjCLiteral) {
347cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9Hans Wennborg  // %n is different from other conversion specifiers; don't try to fix it.
348cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9Hans Wennborg  if (CS.getKind() == ConversionSpecifier::nArg)
349cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9Hans Wennborg    return false;
350cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9Hans Wennborg
351153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  // Handle Objective-C objects first. Note that while the '%@' specifier will
352153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  // not warn for structure pointer or void pointer arguments (because that's
353153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  // how CoreFoundation objects are implemented), we only show a fixit for '%@'
354153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  // if we know it's an object (block, id, class, or __attribute__((NSObject))).
355153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  if (QT->isObjCRetainableType()) {
356153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    if (!IsObjCLiteral)
357153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose      return false;
358153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose
359153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    CS.setKind(ConversionSpecifier::ObjCObjArg);
360153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose
361153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    // Disable irrelevant flags
362153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    HasThousandsGrouping = false;
363153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    HasPlusPrefix = false;
364153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    HasSpacePrefix = false;
365153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    HasAlternativeForm = false;
366153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    HasLeadingZeroes = false;
367153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    Precision.setHowSpecified(OptionalAmount::NotSpecified);
368153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    LM.setKind(LengthModifier::None);
369153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose
370153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    return true;
371153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  }
372153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose
373153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  // Handle strings next (char *, wchar_t *)
3743bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
37599196b1031d37d37f395a3291ccdd12a3fc01242Ted Kremenek    CS.setKind(ConversionSpecifier::sArg);
3763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
377876e994957472eda4b40136d4e1d6e08e2be338fTom Care    // Disable irrelevant flags
378876e994957472eda4b40136d4e1d6e08e2be338fTom Care    HasAlternativeForm = 0;
379876e994957472eda4b40136d4e1d6e08e2be338fTom Care    HasLeadingZeroes = 0;
380876e994957472eda4b40136d4e1d6e08e2be338fTom Care
3813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    // Set the long length modifier for wide characters
3823bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    if (QT->getPointeeType()->isWideCharType())
3833bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      LM.setKind(LengthModifier::AsWideChar);
384117348caf0a8f91782e9e32e32a8689576f394d7Hans Wennborg    else
385117348caf0a8f91782e9e32e32a8689576f394d7Hans Wennborg      LM.setKind(LengthModifier::None);
3863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
3873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    return true;
3883bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
3893bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
390033a9c0804f48119a03b73a2af42a04d4d0294ceJordan Rose  // If it's an enum, get its underlying type.
391033a9c0804f48119a03b73a2af42a04d4d0294ceJordan Rose  if (const EnumType *ETy = QT->getAs<EnumType>())
392033a9c0804f48119a03b73a2af42a04d4d0294ceJordan Rose    QT = ETy->getDecl()->getIntegerType();
393033a9c0804f48119a03b73a2af42a04d4d0294ceJordan Rose
3943bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // We can only work with builtin types.
3953bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  const BuiltinType *BT = QT->getAs<BuiltinType>();
3962dde35bc626153492f5f58202506c88a27fbff5bJohn McCall  if (!BT)
3972dde35bc626153492f5f58202506c88a27fbff5bJohn McCall    return false;
398876e994957472eda4b40136d4e1d6e08e2be338fTom Care
3993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Set length modifier
4003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  switch (BT->getKind()) {
40106d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Bool:
40206d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::WChar_U:
40306d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::WChar_S:
40406d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Char16:
40506d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Char32:
40606d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::UInt128:
40706d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Int128:
408aa4a99b4a62615db243f7a5c433169f2fc704420Anton Korobeynikov  case BuiltinType::Half:
4092dde35bc626153492f5f58202506c88a27fbff5bJohn McCall    // Various types which are non-trivial to correct.
41006d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman    return false;
41106d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman
4122dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define SIGNED_TYPE(Id, SingletonId)
4132dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define UNSIGNED_TYPE(Id, SingletonId)
4142dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define FLOATING_TYPE(Id, SingletonId)
4152dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define BUILTIN_TYPE(Id, SingletonId) \
4162dde35bc626153492f5f58202506c88a27fbff5bJohn McCall  case BuiltinType::Id:
4172dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#include "clang/AST/BuiltinTypes.def"
41806d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman    // Misc other stuff which doesn't make sense here.
41906d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman    return false;
42006d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman
42106d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::UInt:
42206d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Int:
42306d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Float:
42406d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Double:
425876e994957472eda4b40136d4e1d6e08e2be338fTom Care    LM.setKind(LengthModifier::None);
4263bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
427876e994957472eda4b40136d4e1d6e08e2be338fTom Care
4284d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::Char_U:
4294d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::UChar:
4304d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::Char_S:
4314d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::SChar:
4324d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    LM.setKind(LengthModifier::AsChar);
4334d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    break;
4344d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek
4354d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::Short:
4364d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::UShort:
4374d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    LM.setKind(LengthModifier::AsShort);
4384d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    break;
4394d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek
4403bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::Long:
4413bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::ULong:
4423bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLong);
4433bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
4443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::LongLong:
4463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::ULongLong:
4473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLongLong);
4483bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
4493bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4503bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::LongDouble:
4513bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLongDouble);
4523bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
4533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4543bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
455a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
4564684778993c667246039b4664acbce59dc99440cHans Wennborg  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus0x))
4574684778993c667246039b4664acbce59dc99440cHans Wennborg    namedTypeToLengthModifier(QT, LM);
458a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg
459be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg  // If fixing the length modifier was enough, we are done.
460be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg  const analyze_printf::ArgTypeResult &ATR = getArgType(Ctx, IsObjCLiteral);
461be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg  if (hasValidLengthModifier() && ATR.isValid() && ATR.matchesType(Ctx, QT))
462be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg    return true;
463be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg
4643bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Set conversion specifier and disable any flags which do not apply to it.
4654d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
4664d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) {
46792a6febe130dd9ad726983835297e11b2fa3b93fTed Kremenek    CS.setKind(ConversionSpecifier::cArg);
4684d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    LM.setKind(LengthModifier::None);
4693bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    Precision.setHowSpecified(OptionalAmount::NotSpecified);
4703bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
4713bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasLeadingZeroes = 0;
472e4ee9663168dfb2b4122c768091e30217328c9faTom Care    HasPlusPrefix = 0;
4733bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4743bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
4750c293ea13d452c1a47a05ada5a5ee9acc69c66ccDouglas Gregor  else if (QT->isRealFloatingType()) {
4763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::fArg);
4773bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4783bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  else if (QT->isSignedIntegerType()) {
4793bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::dArg);
4803bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
4813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
482c8c4b4088cf0b3afeda425b25fa7c77d3873b12cDouglas Gregor  else if (QT->isUnsignedIntegerType()) {
483be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg    CS.setKind(ConversionSpecifier::uArg);
4843bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
485e4ee9663168dfb2b4122c768091e30217328c9faTom Care    HasPlusPrefix = 0;
4863060178ad9df29789505c1e6debcfc80a3a13587Chad Rosier  } else {
487b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie    llvm_unreachable("Unexpected type");
4883bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4893bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4903bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  return true;
4913bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care}
4923bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4935f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid PrintfSpecifier::toString(raw_ostream &os) const {
4943bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Whilst some features have no defined order, we are using the order
4950099530a2288df7c2140dd8992b7310b9f6930a9NAKAMURA Takumi  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
4963bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << "%";
4973bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4983bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Positional args
4993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (usesPositionalArg()) {
5003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    os << getPositionalArgIndex() << "$";
5013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
5023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
5033bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Conversion flags
5043bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (IsLeftJustified)    os << "-";
5053bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasPlusPrefix)      os << "+";
5063bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasSpacePrefix)     os << " ";
5073bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasAlternativeForm) os << "#";
5083bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasLeadingZeroes)   os << "0";
5093bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
5103bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Minimum field width
5113bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  FieldWidth.toString(os);
5123bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Precision
5133bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  Precision.toString(os);
5143bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Length modifier
5153bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << LM.toString();
5163bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Conversion specifier
5173bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << CS.toString();
5183bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care}
519e4ee9663168dfb2b4122c768091e30217328c9faTom Care
520826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidPlusPrefix() const {
521e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasPlusPrefix)
522e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
523e4ee9663168dfb2b4122c768091e30217328c9faTom Care
524e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The plus prefix only makes sense for signed conversions
525e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
526e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
527e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
528e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
529e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
530e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
531e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
532e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
533e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
534e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
535e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
536e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
537e4ee9663168dfb2b4122c768091e30217328c9faTom Care
538e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
539e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
540e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
541e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
542e4ee9663168dfb2b4122c768091e30217328c9faTom Care
543826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidAlternativeForm() const {
544e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasAlternativeForm)
545e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
546e4ee9663168dfb2b4122c768091e30217328c9faTom Care
5472e6c19abcf97c25f4d7458a9db89c5ab0158717dAnders Carlsson  // Alternate form flag only valid with the oxXaAeEfFgG conversions
548e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
549e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
550e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
5512e6c19abcf97c25f4d7458a9db89c5ab0158717dAnders Carlsson  case ConversionSpecifier::XArg:
552e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
553e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
554e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
555e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
556e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
557e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
558e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
559e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
560e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
561e4ee9663168dfb2b4122c768091e30217328c9faTom Care
562e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
563e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
564e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
565e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
566e4ee9663168dfb2b4122c768091e30217328c9faTom Care
567826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidLeadingZeros() const {
568e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasLeadingZeroes)
569e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
570e4ee9663168dfb2b4122c768091e30217328c9faTom Care
571e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
572e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
573e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
574e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
575e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
576e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::uArg:
577e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
578e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::XArg:
579e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
580e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
581e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
582e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
583e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
584e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
585e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
586e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
587e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
588e4ee9663168dfb2b4122c768091e30217328c9faTom Care
589e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
590e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
591e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
592e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
593e4ee9663168dfb2b4122c768091e30217328c9faTom Care
594826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidSpacePrefix() const {
595e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasSpacePrefix)
596e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
597e4ee9663168dfb2b4122c768091e30217328c9faTom Care
598e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The space prefix only makes sense for signed conversions
599e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
600e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
601e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
602e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
603e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
604e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
605e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
606e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
607e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
608e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
609e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
610e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
611e4ee9663168dfb2b4122c768091e30217328c9faTom Care
612e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
613e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
614e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
615e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
616e4ee9663168dfb2b4122c768091e30217328c9faTom Care
617826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidLeftJustified() const {
618e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!IsLeftJustified)
619e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
620e4ee9663168dfb2b4122c768091e30217328c9faTom Care
621e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The left justified flag is valid for all conversions except n
622e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
62335d353b47bce29200b910371dd9b8ba7f3058ab8Ted Kremenek  case ConversionSpecifier::nArg:
624e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
625e4ee9663168dfb2b4122c768091e30217328c9faTom Care
626e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
627e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
628e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
629e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
630e4ee9663168dfb2b4122c768091e30217328c9faTom Care
63165197b4b0c55bb74af0450230d61ee9461223721Ted Kremenekbool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
63265197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  if (!HasThousandsGrouping)
63365197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    return true;
634dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi
63565197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  switch (CS.getKind()) {
63665197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::dArg:
63765197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::iArg:
63865197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::uArg:
63965197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::fArg:
64065197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::FArg:
64165197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::gArg:
64265197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::GArg:
64365197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek      return true;
64465197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    default:
64565197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek      return false;
64665197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  }
64765197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek}
64865197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek
649826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidPrecision() const {
650e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
651e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
652e4ee9663168dfb2b4122c768091e30217328c9faTom Care
653e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Precision is only valid with the diouxXaAeEfFgGs conversions
654e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
655e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
656e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
657e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
658e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::uArg:
659e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
660e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::XArg:
661e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
662e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
663e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
664e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
665e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
666e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
667e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
668e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
66999196b1031d37d37f395a3291ccdd12a3fc01242Ted Kremenek  case ConversionSpecifier::sArg:
670e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
671e4ee9663168dfb2b4122c768091e30217328c9faTom Care
672e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
673e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
674e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
675e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
676826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidFieldWidth() const {
677e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
678e4ee9663168dfb2b4122c768091e30217328c9faTom Care      return true;
679e4ee9663168dfb2b4122c768091e30217328c9faTom Care
680e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The field width is valid for all conversions except n
681e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
68235d353b47bce29200b910371dd9b8ba7f3058ab8Ted Kremenek  case ConversionSpecifier::nArg:
683e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
684e4ee9663168dfb2b4122c768091e30217328c9faTom Care
685e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
686e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
687e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
688e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
689