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"
1755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Basic/TargetInfo.h"
188f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
19f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborgusing clang::analyze_format_string::ArgType;
20826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing clang::analyze_format_string::FormatStringHandler;
21826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing clang::analyze_format_string::LengthModifier;
22826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing clang::analyze_format_string::OptionalAmount;
236ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenekusing clang::analyze_format_string::ConversionSpecifier;
24826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing clang::analyze_printf::PrintfSpecifier;
25efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek
26808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenekusing namespace clang;
278f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
28826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenektypedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
29826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek        PrintfSpecifierResult;
304e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
314e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
324e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods for parsing format strings.
334e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
348f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
35826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing analyze_format_string::ParseNonPositionAmount;
36efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek
37826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekstatic bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
38efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek                           const char *Start, const char *&Beg, const char *E,
39efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek                           unsigned *argIndex) {
40efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (argIndex) {
41efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
423060178ad9df29789505c1e6debcfc80a3a13587Chad Rosier  } else {
43efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
44826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                           analyze_format_string::PrecisionPos);
45efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    if (Amt.isInvalid())
46efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek      return true;
47efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    FS.setPrecision(Amt);
48efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  }
49efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  return false;
50efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek}
51efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek
52826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekstatic PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
5374d56a168966ff015824279a24aaf566180ed97dTed Kremenek                                                  const char *&Beg,
547f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek                                                  const char *E,
55d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg                                                  unsigned &argIndex,
56275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose                                                  const LangOptions &LO,
57275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose                                                  const TargetInfo &Target) {
584e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
596ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  using namespace clang::analyze_format_string;
604b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenek  using namespace clang::analyze_printf;
614e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
628f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  const char *I = Beg;
636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines  const char *Start = nullptr;
648f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
658f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for a '%' character that indicates the start of a format specifier.
67e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek  for ( ; I != E ; ++I) {
688f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    char c = *I;
698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (c == '\0') {
708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      // Detect spurious null characters, which are likely errors.
718f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      H.HandleNullChar(I);
728f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (c == '%') {
75e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek      Start = I++;  // Record the start of the format specifier.
768f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
778f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
788f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
794e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
808f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // No format specifier found?
818f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (!Start)
828f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return false;
834e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
848f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
858f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
86826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
878f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
888f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
894e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
90826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  PrintfSpecifier FS;
91efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (ParseArgPosition(H, FS, Start, I, E))
92efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    return true;
93efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek
94efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (I == E) {
95efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    // No more characters left?
96826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
97efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    return true;
98efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  }
994e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1008f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for flags (if any).
1018f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  bool hasMore = true;
1028f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  for ( ; I != E; ++I) {
1038f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    switch (*I) {
1048f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      default: hasMore = false; break;
105dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi      case '\'':
106bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek        // FIXME: POSIX specific.  Always accept?
107bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek        FS.setHasThousandsGrouping(I);
108bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek        break;
109e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '-': FS.setIsLeftJustified(I); break;
110e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '+': FS.setHasPlusPrefix(I); break;
111e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case ' ': FS.setHasSpacePrefix(I); break;
112e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '#': FS.setHasAlternativeForm(I); break;
113e4ee9663168dfb2b4122c768091e30217328c9faTom Care      case '0': FS.setHasLeadingZeros(I); break;
1148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1158f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (!hasMore)
1168f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      break;
1174e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
1188f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1198f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1208f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
121826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1228f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1244e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1258f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for the field width (if any).
126efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (ParseFieldWidth(H, FS, Start, I, E,
1276bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                      FS.usesPositionalArg() ? nullptr : &argIndex))
128efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    return true;
1294e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1308f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (I == E) {
1318f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
132826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1338f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1344e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
1354e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  // Look for the precision (if any).
1378f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  if (*I == '.') {
138808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek    ++I;
1398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (I == E) {
140826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      H.HandleIncompleteSpecifier(Start, E - Start);
1418f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1428f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1434e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
144efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek    if (ParsePrecision(H, FS, Start, I, E,
1456bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines                       FS.usesPositionalArg() ? nullptr : &argIndex))
146efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek      return true;
1478f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1488f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (I == E) {
1498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      // No more characters left?
150826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      H.HandleIncompleteSpecifier(Start, E - Start);
1518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek      return true;
1528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    }
1538f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
1548f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
1558f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Look for the length modifier.
156d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg  if (ParseLengthModifier(FS, I, E, LO) && I == E) {
1578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // No more characters left?
158826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    H.HandleIncompleteSpecifier(Start, E - Start);
1598f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    return true;
1608f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
161df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek
1624dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek  if (*I == '\0') {
163df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    // Detect spurious null characters, which are likely errors.
164df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    H.HandleNullChar(I);
165df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    return true;
1664dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek  }
1674e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
1688f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Finally, look for the conversion specifier.
169a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  const char *conversionPosition = I++;
17026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
171a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek  switch (*conversionPosition) {
1728f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    default:
17326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek      break;
174c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek    // C99: 7.19.6.1 (section 8).
17587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case '%': k = ConversionSpecifier::PercentArg;   break;
17687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'A': k = ConversionSpecifier::AArg; break;
177a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'E': k = ConversionSpecifier::EArg; break;
17887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'F': k = ConversionSpecifier::FArg; break;
179a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'G': k = ConversionSpecifier::GArg; break;
18087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'X': k = ConversionSpecifier::XArg; break;
181a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek    case 'a': k = ConversionSpecifier::aArg; break;
18292a6febe130dd9ad726983835297e11b2fa3b93fTed Kremenek    case 'c': k = ConversionSpecifier::cArg; break;
18387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'd': k = ConversionSpecifier::dArg; break;
18487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'e': k = ConversionSpecifier::eArg; break;
18587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'f': k = ConversionSpecifier::fArg; break;
18687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'g': k = ConversionSpecifier::gArg; break;
18787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'i': k = ConversionSpecifier::iArg; break;
18835d353b47bce29200b910371dd9b8ba7f3058ab8Ted Kremenek    case 'n': k = ConversionSpecifier::nArg; break;
18987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'o': k = ConversionSpecifier::oArg; break;
19047ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer    case 'p': k = ConversionSpecifier::pArg; break;
19147ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer    case 's': k = ConversionSpecifier::sArg; break;
19287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'u': k = ConversionSpecifier::uArg; break;
19387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'x': k = ConversionSpecifier::xArg; break;
194bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek    // POSIX specific.
19587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case 'C': k = ConversionSpecifier::CArg; break;
196de183a48dd8fcff5e0343e84c8a6b563088447ceTed Kremenek    case 'S': k = ConversionSpecifier::SArg; break;
197c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek    // Objective-C.
1984dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek    case '@': k = ConversionSpecifier::ObjCObjArg; break;
199df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek    // Glibc specific.
2004dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek    case 'm': k = ConversionSpecifier::PrintErrno; break;
201275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose    // Apple-specific
202275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose    case 'D':
203275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose      if (Target.getTriple().isOSDarwin())
204275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose        k = ConversionSpecifier::DArg;
205275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose      break;
206275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose    case 'O':
207275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose      if (Target.getTriple().isOSDarwin())
208275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose        k = ConversionSpecifier::OArg;
209275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose      break;
210275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose    case 'U':
211275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose      if (Target.getTriple().isOSDarwin())
212275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose        k = ConversionSpecifier::UArg;
213275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose      break;
2148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  }
2156ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  PrintfConversionSpecifier CS(conversionPosition, k);
2167f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek  FS.setConversionSpecifier(CS);
217efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
2187f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek    FS.setArgIndex(argIndex++);
21926ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek
22026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  if (k == ConversionSpecifier::InvalidSpecifier) {
2217f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek    // Assume the conversion takes one argument.
2227966297a70996977f167a8676568f02f4283bdd6Ted Kremenek    return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
22326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek  }
224826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  return PrintfSpecifierResult(Start, FS);
2258f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
2268f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
227826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
228826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                                     const char *I,
229d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg                                                     const char *E,
230275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose                                                     const LangOptions &LO,
231275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose                                                     const TargetInfo &Target) {
2327f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
2337f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek  unsigned argIndex = 0;
2347f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
2358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  // Keep looking for a format specifier until we have exhausted the string.
2368f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  while (I != E) {
237d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
238275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose                                                            LO, Target);
23926ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // Did a fail-stop error of any kind occur when parsing the specifier?
24026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // If so, don't do any more processing.
24126ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    if (FSR.shouldStop())
2421ad23d62007162df82b58bca31b4aa277a5f6586Dmitri Gribenko      return true;
24326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // Did we exhaust the string or encounter an error that
24426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek    // we can recover from?
2458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    if (!FSR.hasValue())
24626ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek      continue;
2478f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek    // We have a format specifier.  Pass it to the callback.
248826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
249a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek                                 I - FSR.getStart()))
2504dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek      return true;
2514e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  }
2524e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek  assert(I == E && "Format string not exhausted");
2538f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek  return false;
2548f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}
2558f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek
2564e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===//
257826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// Methods on PrintfSpecifier.
25833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===//
25933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
260f3749f4168c5cee59627a681ca4ca6e4116d0761Hans WennborgArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
261f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg                                    bool IsObjCLiteral) const {
2626ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  const PrintfConversionSpecifier &CS = getConversionSpecifier();
263dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi
26433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (!CS.consumesDataArgument())
265f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg    return ArgType::Invalid();
2664e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
2679325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek  if (CS.getKind() == ConversionSpecifier::cArg)
2689325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek    switch (LM.getKind()) {
2699325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek      case LengthModifier::None: return Ctx.IntTy;
270f4f0c6095d1f481b94c6821c65e3bf1c9df42af7Hans Wennborg      case LengthModifier::AsLong:
271f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType(ArgType::WIntTy, "wint_t");
2729325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek      default:
273f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType::Invalid();
2749325eaf08fcccbc0d038e703f570c64daacdaa31Ted Kremenek    }
275dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi
27633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (CS.isIntArg())
2773bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    switch (LM.getKind()) {
2783bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongDouble:
2799d24c2cbd9cf1b7c165ccb13221f2efb2f4b49b0Ted Kremenek        // GNU extension.
2809d24c2cbd9cf1b7c165ccb13221f2efb2f4b49b0Ted Kremenek        return Ctx.LongLongTy;
28147ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::None:
28247ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer        return Ctx.IntTy;
28347ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::AsInt32:
28447ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer        return ArgType(Ctx.IntTy, "__int32");
285f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg      case LengthModifier::AsChar: return ArgType::AnyCharTy;
2863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsShort: return Ctx.ShortTy;
2873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLong: return Ctx.LongTy;
28832addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg      case LengthModifier::AsLongLong:
28932addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg      case LengthModifier::AsQuad:
29032addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg        return Ctx.LongLongTy;
29147ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::AsInt64:
29247ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer        return ArgType(Ctx.LongLongTy, "__int64");
293a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg      case LengthModifier::AsIntMax:
294f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType(Ctx.getIntMaxType(), "intmax_t");
29529e97cb35fab314388f62b68fefa78947e93c1dcHans Wennborg      case LengthModifier::AsSizeT:
29629e97cb35fab314388f62b68fefa78947e93c1dcHans Wennborg        // FIXME: How to get the corresponding signed version of size_t?
297f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType();
29847ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::AsInt3264:
299df72071db0ddfd7264485105c19230c315e8ce2cDavid Majnemer        return Ctx.getTargetInfo().getTriple().isArch64Bit()
300df72071db0ddfd7264485105c19230c315e8ce2cDavid Majnemer                   ? ArgType(Ctx.LongLongTy, "__int64")
301df72071db0ddfd7264485105c19230c315e8ce2cDavid Majnemer                   : ArgType(Ctx.IntTy, "__int32");
302a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg      case LengthModifier::AsPtrDiff:
303f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
304d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg      case LengthModifier::AsAllocate:
30537969b7e14d6a4dfd934ef6d3738cc90b832ec1dHans Wennborg      case LengthModifier::AsMAllocate:
306f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType::Invalid();
30733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    }
30833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
30933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  if (CS.isUIntArg())
3103bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    switch (LM.getKind()) {
3113bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLongDouble:
3129d24c2cbd9cf1b7c165ccb13221f2efb2f4b49b0Ted Kremenek        // GNU extension.
3139d24c2cbd9cf1b7c165ccb13221f2efb2f4b49b0Ted Kremenek        return Ctx.UnsignedLongLongTy;
31447ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::None:
31547ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer        return Ctx.UnsignedIntTy;
31647ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::AsInt32:
31747ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer        return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
3183bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
3193bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
3203bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
32132addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg      case LengthModifier::AsLongLong:
32232addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg      case LengthModifier::AsQuad:
32332addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg        return Ctx.UnsignedLongLongTy;
32447ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::AsInt64:
32547ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer        return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
326a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg      case LengthModifier::AsIntMax:
327f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
3283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsSizeT:
329f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType(Ctx.getSizeType(), "size_t");
33047ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::AsInt3264:
33147ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer        return Ctx.getTargetInfo().getTriple().isArch64Bit()
332df72071db0ddfd7264485105c19230c315e8ce2cDavid Majnemer                   ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
333df72071db0ddfd7264485105c19230c315e8ce2cDavid Majnemer                   : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
3343bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      case LengthModifier::AsPtrDiff:
33533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // FIXME: How to get the corresponding unsigned
33633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek        // version of ptrdiff_t?
337f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType();
338d02deebce5f1b283101e035a7f5d5bab0d2068ecHans Wennborg      case LengthModifier::AsAllocate:
33937969b7e14d6a4dfd934ef6d3738cc90b832ec1dHans Wennborg      case LengthModifier::AsMAllocate:
340f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType::Invalid();
34133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek    }
3424e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek
343f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek  if (CS.isDoubleArg()) {
3443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    if (LM.getKind() == LengthModifier::AsLongDouble)
345f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek      return Ctx.LongDoubleTy;
346c9a89fec60a20eb3269caa95eca048d45ab215adTed Kremenek    return Ctx.DoubleTy;
347f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek  }
3487f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
349f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg  if (CS.getKind() == ConversionSpecifier::nArg) {
350f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg    switch (LM.getKind()) {
351f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::None:
352f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg        return ArgType::PtrTo(Ctx.IntTy);
353f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsChar:
354f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg        return ArgType::PtrTo(Ctx.SignedCharTy);
355f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsShort:
356f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg        return ArgType::PtrTo(Ctx.ShortTy);
357f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsLong:
358f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg        return ArgType::PtrTo(Ctx.LongTy);
359f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsLongLong:
360f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsQuad:
361f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg        return ArgType::PtrTo(Ctx.LongLongTy);
362f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsIntMax:
363f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg        return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
364f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsSizeT:
365f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg        return ArgType(); // FIXME: ssize_t
366f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsPtrDiff:
367f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg        return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
368f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsLongDouble:
369f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg        return ArgType(); // FIXME: Is this a known extension?
370f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsAllocate:
371f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg      case LengthModifier::AsMAllocate:
37247ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::AsInt32:
37347ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::AsInt3264:
37447ad6ce1afad6b70927347dfa15e0f1dc76bf5bbDavid Majnemer      case LengthModifier::AsInt64:
375f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg        return ArgType::Invalid();
376f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg    }
377f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg  }
378f7158fa034174d2756736d1032b75d01d9deeb4cHans Wennborg
37987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek  switch (CS.getKind()) {
380630821869c4ec4604ab479d66e5ff81147a858e1Hans Wennborg    case ConversionSpecifier::sArg:
381339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber      if (LM.getKind() == LengthModifier::AsWideChar) {
382339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber        if (IsObjCLiteral)
3832cd3440369d9241173e994485ddf2589a50a7d80Jordan Rose          return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
3842cd3440369d9241173e994485ddf2589a50a7d80Jordan Rose                         "const unichar *");
385f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg        return ArgType(ArgType::WCStrTy, "wchar_t *");
386339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber      }
387f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg      return ArgType::CStrTy;
388de183a48dd8fcff5e0343e84c8a6b563088447ceTed Kremenek    case ConversionSpecifier::SArg:
389339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber      if (IsObjCLiteral)
3902cd3440369d9241173e994485ddf2589a50a7d80Jordan Rose        return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
3912cd3440369d9241173e994485ddf2589a50a7d80Jordan Rose                       "const unichar *");
392f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg      return ArgType(ArgType::WCStrTy, "wchar_t *");
39387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    case ConversionSpecifier::CArg:
394339b9072e26a2a0fe796dc69c4d28d964d0ec86dNico Weber      if (IsObjCLiteral)
3952cd3440369d9241173e994485ddf2589a50a7d80Jordan Rose        return ArgType(Ctx.UnsignedShortTy, "unichar");
39615f92bad58c8650b1306729744b1a1230197497aHans Wennborg      return ArgType(Ctx.WideCharTy, "wchar_t");
39766932056da99d2441e27c10b27c82706671e1dbfTed Kremenek    case ConversionSpecifier::pArg:
398f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg      return ArgType::CPointerTy;
399e6ca97f2aeb301e28d20988b27c4297a9b540991Ted Kremenek    case ConversionSpecifier::ObjCObjArg:
400f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg      return ArgType::ObjCPointerTy;
40187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek    default:
40287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek      break;
40387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek  }
4047f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek
40533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek  // FIXME: Handle other cases.
406f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg  return ArgType();
40733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek}
40833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek
409be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborgbool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
410be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg                              ASTContext &Ctx, bool IsObjCLiteral) {
411cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9Hans Wennborg  // %n is different from other conversion specifiers; don't try to fix it.
412cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9Hans Wennborg  if (CS.getKind() == ConversionSpecifier::nArg)
413cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9Hans Wennborg    return false;
414cec9ce49dcf4b4b768043f96c8ef8c1d4cdbb6b9Hans Wennborg
415153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  // Handle Objective-C objects first. Note that while the '%@' specifier will
416153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  // not warn for structure pointer or void pointer arguments (because that's
417153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  // how CoreFoundation objects are implemented), we only show a fixit for '%@'
418153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  // if we know it's an object (block, id, class, or __attribute__((NSObject))).
419153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  if (QT->isObjCRetainableType()) {
420153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    if (!IsObjCLiteral)
421153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose      return false;
422153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose
423153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    CS.setKind(ConversionSpecifier::ObjCObjArg);
424153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose
425153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    // Disable irrelevant flags
426153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    HasThousandsGrouping = false;
427153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    HasPlusPrefix = false;
428153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    HasSpacePrefix = false;
429153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    HasAlternativeForm = false;
430153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    HasLeadingZeroes = false;
431153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    Precision.setHowSpecified(OptionalAmount::NotSpecified);
432153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    LM.setKind(LengthModifier::None);
433153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose
434153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose    return true;
435153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  }
436153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose
437153acdb7310b20a72e608cbb10946621f161eb70Jordan Rose  // Handle strings next (char *, wchar_t *)
4383bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
43999196b1031d37d37f395a3291ccdd12a3fc01242Ted Kremenek    CS.setKind(ConversionSpecifier::sArg);
4403bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
441876e994957472eda4b40136d4e1d6e08e2be338fTom Care    // Disable irrelevant flags
442876e994957472eda4b40136d4e1d6e08e2be338fTom Care    HasAlternativeForm = 0;
443876e994957472eda4b40136d4e1d6e08e2be338fTom Care    HasLeadingZeroes = 0;
444876e994957472eda4b40136d4e1d6e08e2be338fTom Care
4453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    // Set the long length modifier for wide characters
4463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    if (QT->getPointeeType()->isWideCharType())
4473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care      LM.setKind(LengthModifier::AsWideChar);
448117348caf0a8f91782e9e32e32a8689576f394d7Hans Wennborg    else
449117348caf0a8f91782e9e32e32a8689576f394d7Hans Wennborg      LM.setKind(LengthModifier::None);
4503bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
4513bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    return true;
4523bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
4533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
454033a9c0804f48119a03b73a2af42a04d4d0294ceJordan Rose  // If it's an enum, get its underlying type.
455033a9c0804f48119a03b73a2af42a04d4d0294ceJordan Rose  if (const EnumType *ETy = QT->getAs<EnumType>())
456033a9c0804f48119a03b73a2af42a04d4d0294ceJordan Rose    QT = ETy->getDecl()->getIntegerType();
457033a9c0804f48119a03b73a2af42a04d4d0294ceJordan Rose
4583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // We can only work with builtin types.
4593bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  const BuiltinType *BT = QT->getAs<BuiltinType>();
4602dde35bc626153492f5f58202506c88a27fbff5bJohn McCall  if (!BT)
4612dde35bc626153492f5f58202506c88a27fbff5bJohn McCall    return false;
462876e994957472eda4b40136d4e1d6e08e2be338fTom Care
4633bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Set length modifier
4643bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  switch (BT->getKind()) {
46506d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Bool:
46606d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::WChar_U:
46706d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::WChar_S:
46806d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Char16:
46906d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Char32:
47006d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::UInt128:
47106d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Int128:
472aa4a99b4a62615db243f7a5c433169f2fc704420Anton Korobeynikov  case BuiltinType::Half:
4732dde35bc626153492f5f58202506c88a27fbff5bJohn McCall    // Various types which are non-trivial to correct.
47406d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman    return false;
47506d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman
4762dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define SIGNED_TYPE(Id, SingletonId)
4772dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define UNSIGNED_TYPE(Id, SingletonId)
4782dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define FLOATING_TYPE(Id, SingletonId)
4792dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#define BUILTIN_TYPE(Id, SingletonId) \
4802dde35bc626153492f5f58202506c88a27fbff5bJohn McCall  case BuiltinType::Id:
4812dde35bc626153492f5f58202506c88a27fbff5bJohn McCall#include "clang/AST/BuiltinTypes.def"
48206d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman    // Misc other stuff which doesn't make sense here.
48306d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman    return false;
48406d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman
48506d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::UInt:
48606d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Int:
48706d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Float:
48806d88ec4204be7af2cf935f39a3e3391d281ad52Eli Friedman  case BuiltinType::Double:
489876e994957472eda4b40136d4e1d6e08e2be338fTom Care    LM.setKind(LengthModifier::None);
4903bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
491876e994957472eda4b40136d4e1d6e08e2be338fTom Care
4924d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::Char_U:
4934d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::UChar:
4944d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::Char_S:
4954d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::SChar:
4964d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    LM.setKind(LengthModifier::AsChar);
4974d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    break;
4984d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek
4994d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::Short:
5004d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  case BuiltinType::UShort:
5014d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    LM.setKind(LengthModifier::AsShort);
5024d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    break;
5034d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek
5043bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::Long:
5053bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::ULong:
5063bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLong);
5073bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
5083bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
5093bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::LongLong:
5103bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::ULongLong:
5113bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLongLong);
5123bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
5133bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
5143bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  case BuiltinType::LongDouble:
5153bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    LM.setKind(LengthModifier::AsLongDouble);
5163bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    break;
5173bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
5183bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
519a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
52080ad52f327b532bded5c5b0ee38779d841c6cd35Richard Smith  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
5214684778993c667246039b4664acbce59dc99440cHans Wennborg    namedTypeToLengthModifier(QT, LM);
522a7da2155167676a6a5d9fca4de947a9cab2a4908Hans Wennborg
523242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose  // If fixing the length modifier was enough, we might be done.
524bbb6bb4952b77e57b842b4d3096848123ae690e7Jordan Rose  if (hasValidLengthModifier(Ctx.getTargetInfo())) {
525242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose    // If we're going to offer a fix anyway, make sure the sign matches.
526242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose    switch (CS.getKind()) {
527242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose    case ConversionSpecifier::uArg:
528242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose    case ConversionSpecifier::UArg:
529242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose      if (QT->isSignedIntegerType())
530242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose        CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
531242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose      break;
532242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose    case ConversionSpecifier::dArg:
533242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose    case ConversionSpecifier::DArg:
534242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose    case ConversionSpecifier::iArg:
535cdbe1e0d85d7d32452dd1c52758d7bfaa1c0663bJordan Rose      if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
536242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose        CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
537242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose      break;
538242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose    default:
539242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose      // Other specifiers do not have signed/unsigned variants.
540242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose      break;
541242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose    }
542242ae3d6805185fcb4fd45e96af5beba93e3532cJordan Rose
543bbb6bb4952b77e57b842b4d3096848123ae690e7Jordan Rose    const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
544bbb6bb4952b77e57b842b4d3096848123ae690e7Jordan Rose    if (ATR.isValid() && ATR.matchesType(Ctx, QT))
545bbb6bb4952b77e57b842b4d3096848123ae690e7Jordan Rose      return true;
546bbb6bb4952b77e57b842b4d3096848123ae690e7Jordan Rose  }
547be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg
5483bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Set conversion specifier and disable any flags which do not apply to it.
5494d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
550ff7be48165548c9c01492010609d166973607068Jordan Rose  if (!isa<TypedefType>(QT) && QT->isCharType()) {
55192a6febe130dd9ad726983835297e11b2fa3b93fTed Kremenek    CS.setKind(ConversionSpecifier::cArg);
5524d8ae4d57ed18d60da4d3786fb740607aa7c3688Ted Kremenek    LM.setKind(LengthModifier::None);
5533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    Precision.setHowSpecified(OptionalAmount::NotSpecified);
5543bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
5553bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasLeadingZeroes = 0;
556e4ee9663168dfb2b4122c768091e30217328c9faTom Care    HasPlusPrefix = 0;
5573bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
5583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
5590c293ea13d452c1a47a05ada5a5ee9acc69c66ccDouglas Gregor  else if (QT->isRealFloatingType()) {
5603bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::fArg);
5613bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
5623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  else if (QT->isSignedIntegerType()) {
5633bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    CS.setKind(ConversionSpecifier::dArg);
5643bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
5653bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
566c8c4b4088cf0b3afeda425b25fa7c77d3873b12cDouglas Gregor  else if (QT->isUnsignedIntegerType()) {
567be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg    CS.setKind(ConversionSpecifier::uArg);
5683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    HasAlternativeForm = 0;
569e4ee9663168dfb2b4122c768091e30217328c9faTom Care    HasPlusPrefix = 0;
5703060178ad9df29789505c1e6debcfc80a3a13587Chad Rosier  } else {
571b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie    llvm_unreachable("Unexpected type");
5723bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
5733bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
5743bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  return true;
5753bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care}
5763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
5775f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnervoid PrintfSpecifier::toString(raw_ostream &os) const {
5783bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Whilst some features have no defined order, we are using the order
5790099530a2288df7c2140dd8992b7310b9f6930a9NAKAMURA Takumi  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
5803bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << "%";
5813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
5823bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Positional args
5833bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (usesPositionalArg()) {
5843bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care    os << getPositionalArgIndex() << "$";
5853bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  }
5863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
5873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Conversion flags
5883bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (IsLeftJustified)    os << "-";
5893bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasPlusPrefix)      os << "+";
5903bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasSpacePrefix)     os << " ";
5913bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasAlternativeForm) os << "#";
5923bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  if (HasLeadingZeroes)   os << "0";
5933bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care
5943bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Minimum field width
5953bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  FieldWidth.toString(os);
5963bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Precision
5973bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  Precision.toString(os);
5983bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Length modifier
5993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << LM.toString();
6003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  // Conversion specifier
6013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care  os << CS.toString();
6023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care}
603e4ee9663168dfb2b4122c768091e30217328c9faTom Care
604826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidPlusPrefix() const {
605e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasPlusPrefix)
606e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
607e4ee9663168dfb2b4122c768091e30217328c9faTom Care
608e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The plus prefix only makes sense for signed conversions
609e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
610e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
611275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose  case ConversionSpecifier::DArg:
612e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
613e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
614e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
615e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
616e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
617e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
618e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
619e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
620e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
621e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
622e4ee9663168dfb2b4122c768091e30217328c9faTom Care
623e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
624e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
625e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
626e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
627e4ee9663168dfb2b4122c768091e30217328c9faTom Care
628826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidAlternativeForm() const {
629e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasAlternativeForm)
630e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
631e4ee9663168dfb2b4122c768091e30217328c9faTom Care
6322e6c19abcf97c25f4d7458a9db89c5ab0158717dAnders Carlsson  // Alternate form flag only valid with the oxXaAeEfFgG conversions
633e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
634e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
635275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose  case ConversionSpecifier::OArg:
636e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
6372e6c19abcf97c25f4d7458a9db89c5ab0158717dAnders Carlsson  case ConversionSpecifier::XArg:
638e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
639e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
640e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
641e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
642e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
643e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
644e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
645e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
646e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
647e4ee9663168dfb2b4122c768091e30217328c9faTom Care
648e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
649e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
650e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
651e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
652e4ee9663168dfb2b4122c768091e30217328c9faTom Care
653826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidLeadingZeros() const {
654e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasLeadingZeroes)
655e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
656e4ee9663168dfb2b4122c768091e30217328c9faTom Care
657e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
658e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
659e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
660275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose  case ConversionSpecifier::DArg:
661e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
662e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
663275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose  case ConversionSpecifier::OArg:
664e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::uArg:
665275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose  case ConversionSpecifier::UArg:
666e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
667e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::XArg:
668e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
669e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
670e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
671e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
672e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
673e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
674e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
675e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
676e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
677e4ee9663168dfb2b4122c768091e30217328c9faTom Care
678e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
679e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
680e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
681e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
682e4ee9663168dfb2b4122c768091e30217328c9faTom Care
683826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidSpacePrefix() const {
684e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!HasSpacePrefix)
685e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
686e4ee9663168dfb2b4122c768091e30217328c9faTom Care
687e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The space prefix only makes sense for signed conversions
688e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
689e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
690275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose  case ConversionSpecifier::DArg:
691e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
692e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
693e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
694e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
695e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
696e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
697e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
698e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
699e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
700e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
701e4ee9663168dfb2b4122c768091e30217328c9faTom Care
702e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
703e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
704e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
705e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
706e4ee9663168dfb2b4122c768091e30217328c9faTom Care
707826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidLeftJustified() const {
708e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (!IsLeftJustified)
709e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
710e4ee9663168dfb2b4122c768091e30217328c9faTom Care
711e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The left justified flag is valid for all conversions except n
712e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
71335d353b47bce29200b910371dd9b8ba7f3058ab8Ted Kremenek  case ConversionSpecifier::nArg:
714e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
715e4ee9663168dfb2b4122c768091e30217328c9faTom Care
716e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
717e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
718e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
719e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
720e4ee9663168dfb2b4122c768091e30217328c9faTom Care
72165197b4b0c55bb74af0450230d61ee9461223721Ted Kremenekbool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
72265197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  if (!HasThousandsGrouping)
72365197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    return true;
724dfbb02a16ac8c764b5ba1742450513d6212d2f9fNAKAMURA Takumi
72565197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  switch (CS.getKind()) {
72665197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::dArg:
727275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose    case ConversionSpecifier::DArg:
72865197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::iArg:
72965197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::uArg:
730275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose    case ConversionSpecifier::UArg:
73165197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::fArg:
73265197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::FArg:
73365197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::gArg:
73465197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    case ConversionSpecifier::GArg:
73565197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek      return true;
73665197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek    default:
73765197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek      return false;
73865197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  }
73965197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek}
74065197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek
741826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidPrecision() const {
742e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
743e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
744e4ee9663168dfb2b4122c768091e30217328c9faTom Care
745e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // Precision is only valid with the diouxXaAeEfFgGs conversions
746e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
747e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::dArg:
748275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose  case ConversionSpecifier::DArg:
749e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::iArg:
750e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::oArg:
751275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose  case ConversionSpecifier::OArg:
752e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::uArg:
753275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose  case ConversionSpecifier::UArg:
754e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::xArg:
755e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::XArg:
756e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::aArg:
757e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::AArg:
758e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::eArg:
759e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::EArg:
760e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::fArg:
761e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::FArg:
762e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::gArg:
763e4ee9663168dfb2b4122c768091e30217328c9faTom Care  case ConversionSpecifier::GArg:
76499196b1031d37d37f395a3291ccdd12a3fc01242Ted Kremenek  case ConversionSpecifier::sArg:
765e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
766e4ee9663168dfb2b4122c768091e30217328c9faTom Care
767e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
768e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
769e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
770e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
771826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool PrintfSpecifier::hasValidFieldWidth() const {
772e4ee9663168dfb2b4122c768091e30217328c9faTom Care  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
773e4ee9663168dfb2b4122c768091e30217328c9faTom Care      return true;
774e4ee9663168dfb2b4122c768091e30217328c9faTom Care
775e4ee9663168dfb2b4122c768091e30217328c9faTom Care  // The field width is valid for all conversions except n
776e4ee9663168dfb2b4122c768091e30217328c9faTom Care  switch (CS.getKind()) {
77735d353b47bce29200b910371dd9b8ba7f3058ab8Ted Kremenek  case ConversionSpecifier::nArg:
778e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return false;
779e4ee9663168dfb2b4122c768091e30217328c9faTom Care
780e4ee9663168dfb2b4122c768091e30217328c9faTom Care  default:
781e4ee9663168dfb2b4122c768091e30217328c9faTom Care    return true;
782e4ee9663168dfb2b4122c768091e30217328c9faTom Care  }
783e4ee9663168dfb2b4122c768091e30217328c9faTom Care}
784