PrintfFormatString.cpp revision 360784
1139804Simp//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
2139013Sdavidxu//
3112904Sjeff// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4112904Sjeff// See https://llvm.org/LICENSE.txt for license information.
5112904Sjeff// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6112904Sjeff//
7112904Sjeff//===----------------------------------------------------------------------===//
8112904Sjeff//
9112904Sjeff// Handling of format string in printf and friends.  The structure of format
10112904Sjeff// strings for fprintf() are described in C99 7.19.6.1.
11112904Sjeff//
12112904Sjeff//===----------------------------------------------------------------------===//
13112904Sjeff
14112904Sjeff#include "clang/AST/FormatString.h"
15112904Sjeff#include "clang/AST/OSLog.h"
16112904Sjeff#include "FormatStringParsing.h"
17112904Sjeff#include "clang/Basic/TargetInfo.h"
18112904Sjeff
19112904Sjeffusing clang::analyze_format_string::ArgType;
20112904Sjeffusing clang::analyze_format_string::FormatStringHandler;
21112904Sjeffusing clang::analyze_format_string::LengthModifier;
22112904Sjeffusing clang::analyze_format_string::OptionalAmount;
23112904Sjeffusing clang::analyze_format_string::ConversionSpecifier;
24112904Sjeffusing clang::analyze_printf::PrintfSpecifier;
25112904Sjeff
26112904Sjeffusing namespace clang;
27112904Sjeff
28116182Sobrientypedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
29116182Sobrien        PrintfSpecifierResult;
30116182Sobrien
31162536Sdavidxu//===----------------------------------------------------------------------===//
32233045Sdavide// Methods for parsing format strings.
33233045Sdavide//===----------------------------------------------------------------------===//
34112904Sjeff
35112904Sjeffusing analyze_format_string::ParseNonPositionAmount;
36131431Smarcel
37112904Sjeffstatic bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
38115765Sjeff                           const char *Start, const char *&Beg, const char *E,
39112904Sjeff                           unsigned *argIndex) {
40164033Srwatson  if (argIndex) {
41112904Sjeff    FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
42161678Sdavidxu  } else {
43165369Sdavidxu    const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
44161678Sdavidxu                                           analyze_format_string::PrecisionPos);
45112904Sjeff    if (Amt.isInvalid())
46112904Sjeff      return true;
47112904Sjeff    FS.setPrecision(Amt);
48216641Sdavidxu  }
49139013Sdavidxu  return false;
50112904Sjeff}
51112904Sjeff
52139013Sdavidxustatic bool ParseObjCFlags(FormatStringHandler &H, PrintfSpecifier &FS,
53139013Sdavidxu                           const char *FlagBeg, const char *E, bool Warn) {
54139013Sdavidxu   StringRef Flag(FlagBeg, E - FlagBeg);
55139013Sdavidxu   // Currently there is only one flag.
56139013Sdavidxu   if (Flag == "tt") {
57139013Sdavidxu     FS.setHasObjCTechnicalTerm(FlagBeg);
58165369Sdavidxu     return false;
59165369Sdavidxu   }
60205014Snwhitehorn   // Handle either the case of no flag or an invalid flag.
61162536Sdavidxu   if (Warn) {
62162536Sdavidxu     if (Flag == "")
63162536Sdavidxu       H.HandleEmptyObjCModifierFlag(FlagBeg, E  - FlagBeg);
64179970Sdavidxu     else
65179970Sdavidxu       H.HandleInvalidObjCModifierFlag(FlagBeg, E  - FlagBeg);
66179970Sdavidxu   }
67161678Sdavidxu   return true;
68161678Sdavidxu}
69161678Sdavidxu
70161678Sdavidxustatic PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
71161678Sdavidxu                                                  const char *&Beg,
72161678Sdavidxu                                                  const char *E,
73161678Sdavidxu                                                  unsigned &argIndex,
74161678Sdavidxu                                                  const LangOptions &LO,
75161678Sdavidxu                                                  const TargetInfo &Target,
76161678Sdavidxu                                                  bool Warn,
77161678Sdavidxu                                                  bool isFreeBSDKPrintf) {
78161678Sdavidxu
79161678Sdavidxu  using namespace clang::analyze_format_string;
80161678Sdavidxu  using namespace clang::analyze_printf;
81161678Sdavidxu
82161678Sdavidxu  const char *I = Beg;
83161678Sdavidxu  const char *Start = nullptr;
84161678Sdavidxu  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
85161678Sdavidxu
86161678Sdavidxu  // Look for a '%' character that indicates the start of a format specifier.
87161678Sdavidxu  for ( ; I != E ; ++I) {
88161678Sdavidxu    char c = *I;
89115765Sjeff    if (c == '\0') {
90161678Sdavidxu      // Detect spurious null characters, which are likely errors.
91161678Sdavidxu      H.HandleNullChar(I);
92161678Sdavidxu      return true;
93161678Sdavidxu    }
94161678Sdavidxu    if (c == '%') {
95161678Sdavidxu      Start = I++;  // Record the start of the format specifier.
96161678Sdavidxu      break;
97161678Sdavidxu    }
98161678Sdavidxu  }
99161678Sdavidxu
100161678Sdavidxu  // No format specifier found?
101161678Sdavidxu  if (!Start)
102161678Sdavidxu    return false;
103161678Sdavidxu
104161678Sdavidxu  if (I == E) {
105170300Sjeff    // No more characters left?
106170300Sjeff    if (Warn)
107161678Sdavidxu      H.HandleIncompleteSpecifier(Start, E - Start);
108161678Sdavidxu    return true;
109161678Sdavidxu  }
110161678Sdavidxu
111161678Sdavidxu  PrintfSpecifier FS;
112161678Sdavidxu  if (ParseArgPosition(H, FS, Start, I, E))
113161678Sdavidxu    return true;
114161678Sdavidxu
115161678Sdavidxu  if (I == E) {
116161742Sdavidxu    // No more characters left?
117161678Sdavidxu    if (Warn)
118201991Sdavidxu      H.HandleIncompleteSpecifier(Start, E - Start);
119201991Sdavidxu    return true;
120201991Sdavidxu  }
121201991Sdavidxu
122201991Sdavidxu  if (*I == '{') {
123201991Sdavidxu    ++I;
124115765Sjeff    unsigned char PrivacyFlags = 0;
125115765Sjeff    StringRef MatchedStr;
126161678Sdavidxu
127161678Sdavidxu    do {
128201991Sdavidxu      StringRef Str(I, E - I);
129201991Sdavidxu      std::string Match = "^[[:space:]]*"
130201991Sdavidxu                          "(private|public|sensitive|mask\\.[^[:space:],}]*)"
131201991Sdavidxu                          "[[:space:]]*(,|})";
132201991Sdavidxu      llvm::Regex R(Match);
133201991Sdavidxu      SmallVector<StringRef, 2> Matches;
134201991Sdavidxu
135201991Sdavidxu      if (R.match(Str, &Matches)) {
136201991Sdavidxu        MatchedStr = Matches[1];
137201991Sdavidxu        I += Matches[0].size();
138161678Sdavidxu
139138224Sdavidxu        // Set the privacy flag if the privacy annotation in the
140161678Sdavidxu        // comma-delimited segment is at least as strict as the privacy
141161678Sdavidxu        // annotations in previous comma-delimited segments.
142161678Sdavidxu        if (MatchedStr.startswith("mask")) {
143161678Sdavidxu          StringRef MaskType = MatchedStr.substr(sizeof("mask.") - 1);
144201991Sdavidxu          unsigned Size = MaskType.size();
145177848Sdavidxu          if (Warn && (Size == 0 || Size > 8))
146177848Sdavidxu            H.handleInvalidMaskType(MaskType);
147161678Sdavidxu          FS.setMaskType(MaskType);
148201991Sdavidxu        } else if (MatchedStr.equals("sensitive"))
149201991Sdavidxu          PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsSensitive;
150161678Sdavidxu        else if (PrivacyFlags !=
151161678Sdavidxu                 clang::analyze_os_log::OSLogBufferItem::IsSensitive &&
152161678Sdavidxu                 MatchedStr.equals("private"))
153161678Sdavidxu          PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPrivate;
154158377Sdavidxu        else if (PrivacyFlags == 0 && MatchedStr.equals("public"))
155161678Sdavidxu          PrivacyFlags = clang::analyze_os_log::OSLogBufferItem::IsPublic;
156161678Sdavidxu      } else {
157161678Sdavidxu        size_t CommaOrBracePos =
158201991Sdavidxu            Str.find_if([](char c) { return c == ',' || c == '}'; });
159233045Sdavide
160233045Sdavide        if (CommaOrBracePos == StringRef::npos) {
161233045Sdavide          // Neither a comma nor the closing brace was found.
162233045Sdavide          if (Warn)
163138224Sdavidxu            H.HandleIncompleteSpecifier(Start, E - Start);
164115765Sjeff          return true;
165161678Sdavidxu        }
166189756Sdavidxu
167161678Sdavidxu        I += CommaOrBracePos + 1;
168161678Sdavidxu      }
169161678Sdavidxu      // Continue until the closing brace is found.
170161678Sdavidxu    } while (*(I - 1) == ',');
171161678Sdavidxu
172161678Sdavidxu    // Set the privacy flag.
173161678Sdavidxu    switch (PrivacyFlags) {
174161678Sdavidxu    case 0:
175161678Sdavidxu      break;
176161678Sdavidxu    case clang::analyze_os_log::OSLogBufferItem::IsPrivate:
177163709Sjb      FS.setIsPrivate(MatchedStr.data());
178163709Sjb      break;
179163709Sjb    case clang::analyze_os_log::OSLogBufferItem::IsPublic:
180161678Sdavidxu      FS.setIsPublic(MatchedStr.data());
181138224Sdavidxu      break;
182216678Sdavidxu    case clang::analyze_os_log::OSLogBufferItem::IsSensitive:
183216678Sdavidxu      FS.setIsSensitive(MatchedStr.data());
184115765Sjeff      break;
185161678Sdavidxu    default:
186161678Sdavidxu      llvm_unreachable("Unexpected privacy flag value");
187161678Sdavidxu    }
188177848Sdavidxu  }
189177848Sdavidxu
190161678Sdavidxu  // Look for flags (if any).
191179421Sdavidxu  bool hasMore = true;
192138224Sdavidxu  for ( ; I != E; ++I) {
193161678Sdavidxu    switch (*I) {
194115310Sjeff      default: hasMore = false; break;
195227309Sed      case '\'':
196161678Sdavidxu        // FIXME: POSIX specific.  Always accept?
197161678Sdavidxu        FS.setHasThousandsGrouping(I);
198161678Sdavidxu        break;
199233045Sdavide      case '-': FS.setIsLeftJustified(I); break;
200233045Sdavide      case '+': FS.setHasPlusPrefix(I); break;
201233045Sdavide      case ' ': FS.setHasSpacePrefix(I); break;
202233045Sdavide      case '#': FS.setHasAlternativeForm(I); break;
203233045Sdavide      case '0': FS.setHasLeadingZeros(I); break;
204233045Sdavide    }
205161678Sdavidxu    if (!hasMore)
206161678Sdavidxu      break;
207161678Sdavidxu  }
208139013Sdavidxu
209139013Sdavidxu  if (I == E) {
210139257Sdavidxu    // No more characters left?
211139257Sdavidxu    if (Warn)
212177848Sdavidxu      H.HandleIncompleteSpecifier(Start, E - Start);
213177848Sdavidxu    return true;
214161678Sdavidxu  }
215139257Sdavidxu
216163697Sdavidxu  // Look for the field width (if any).
217161678Sdavidxu  if (ParseFieldWidth(H, FS, Start, I, E,
218161678Sdavidxu                      FS.usesPositionalArg() ? nullptr : &argIndex))
219161678Sdavidxu    return true;
220161678Sdavidxu
221161678Sdavidxu  if (I == E) {
222161678Sdavidxu    // No more characters left?
223115310Sjeff    if (Warn)
224177848Sdavidxu      H.HandleIncompleteSpecifier(Start, E - Start);
225177848Sdavidxu    return true;
226177848Sdavidxu  }
227177848Sdavidxu
228170300Sjeff  // Look for the precision (if any).
229170300Sjeff  if (*I == '.') {
230233045Sdavide    ++I;
231161678Sdavidxu    if (I == E) {
232233045Sdavide      if (Warn)
233233045Sdavide        H.HandleIncompleteSpecifier(Start, E - Start);
234233045Sdavide      return true;
235233045Sdavide    }
236233045Sdavide
237233045Sdavide    if (ParsePrecision(H, FS, Start, I, E,
238233045Sdavide                       FS.usesPositionalArg() ? nullptr : &argIndex))
239233045Sdavide      return true;
240233045Sdavide
241233045Sdavide    if (I == E) {
242233045Sdavide      // No more characters left?
243233045Sdavide      if (Warn)
244233045Sdavide        H.HandleIncompleteSpecifier(Start, E - Start);
245233045Sdavide      return true;
246233045Sdavide    }
247233045Sdavide  }
248233045Sdavide
249233045Sdavide  if (ParseVectorModifier(H, FS, I, E, LO))
250233045Sdavide    return true;
251233045Sdavide
252161678Sdavidxu  // Look for the length modifier.
253161678Sdavidxu  if (ParseLengthModifier(FS, I, E, LO) && I == E) {
254179421Sdavidxu    // No more characters left?
255138224Sdavidxu    if (Warn)
256161678Sdavidxu      H.HandleIncompleteSpecifier(Start, E - Start);
257161678Sdavidxu    return true;
258179421Sdavidxu  }
259179421Sdavidxu
260179421Sdavidxu  // Look for the Objective-C modifier flags, if any.
261179421Sdavidxu  // We parse these here, even if they don't apply to
262201991Sdavidxu  // the conversion specifier, and then emit an error
263201991Sdavidxu  // later if the conversion specifier isn't '@'.  This
264201991Sdavidxu  // enables better recovery, and we don't know if
265179421Sdavidxu  // these flags are applicable until later.
266179421Sdavidxu  const char *ObjCModifierFlagsStart = nullptr,
267179421Sdavidxu             *ObjCModifierFlagsEnd = nullptr;
268233045Sdavide  if (*I == '[') {
269233045Sdavide    ObjCModifierFlagsStart = I;
270233045Sdavide    ++I;
271233045Sdavide    auto flagStart = I;
272179421Sdavidxu    for (;; ++I) {
273161678Sdavidxu      ObjCModifierFlagsEnd = I;
274233045Sdavide      if (I == E) {
275233045Sdavide        if (Warn)
276233045Sdavide          H.HandleIncompleteSpecifier(Start, E - Start);
277170300Sjeff        return true;
278161678Sdavidxu      }
279161678Sdavidxu      // Did we find the closing ']'?
280161678Sdavidxu      if (*I == ']') {
281161678Sdavidxu        if (ParseObjCFlags(H, FS, flagStart, I, Warn))
282143149Sdavidxu          return true;
283143149Sdavidxu        ++I;
284143149Sdavidxu        break;
285161678Sdavidxu      }
286161678Sdavidxu      // There are no separators defined yet for multiple
287161678Sdavidxu      // Objective-C modifier flags.  When those are
288201991Sdavidxu      // defined, this is the place to check.
289201991Sdavidxu    }
290161678Sdavidxu  }
291161678Sdavidxu
292161678Sdavidxu  if (*I == '\0') {
293143149Sdavidxu    // Detect spurious null characters, which are likely errors.
294143149Sdavidxu    H.HandleNullChar(I);
295143149Sdavidxu    return true;
296143149Sdavidxu  }
297143149Sdavidxu
298201991Sdavidxu  // Finally, look for the conversion specifier.
299201991Sdavidxu  const char *conversionPosition = I++;
300143149Sdavidxu  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
301143149Sdavidxu  switch (*conversionPosition) {
302143149Sdavidxu    default:
303161678Sdavidxu      break;
304139013Sdavidxu    // C99: 7.19.6.1 (section 8).
305138224Sdavidxu    case '%': k = ConversionSpecifier::PercentArg;   break;
306161678Sdavidxu    case 'A': k = ConversionSpecifier::AArg; break;
307161678Sdavidxu    case 'E': k = ConversionSpecifier::EArg; break;
308138224Sdavidxu    case 'F': k = ConversionSpecifier::FArg; break;
309138224Sdavidxu    case 'G': k = ConversionSpecifier::GArg; break;
310161678Sdavidxu    case 'X': k = ConversionSpecifier::XArg; break;
311161678Sdavidxu    case 'a': k = ConversionSpecifier::aArg; break;
312139013Sdavidxu    case 'c': k = ConversionSpecifier::cArg; break;
313201886Sdavidxu    case 'd': k = ConversionSpecifier::dArg; break;
314179421Sdavidxu    case 'e': k = ConversionSpecifier::eArg; break;
315179421Sdavidxu    case 'f': k = ConversionSpecifier::fArg; break;
316139013Sdavidxu    case 'g': k = ConversionSpecifier::gArg; break;
317139013Sdavidxu    case 'i': k = ConversionSpecifier::iArg; break;
318161678Sdavidxu    case 'n':
319177848Sdavidxu      // Not handled, but reserved in OpenCL.
320161678Sdavidxu      if (!LO.OpenCL)
321138224Sdavidxu        k = ConversionSpecifier::nArg;
322177848Sdavidxu      break;
323139257Sdavidxu    case 'o': k = ConversionSpecifier::oArg; break;
324161678Sdavidxu    case 'p': k = ConversionSpecifier::pArg; break;
325139257Sdavidxu    case 's': k = ConversionSpecifier::sArg; break;
326161678Sdavidxu    case 'u': k = ConversionSpecifier::uArg; break;
327177848Sdavidxu    case 'x': k = ConversionSpecifier::xArg; break;
328139257Sdavidxu    // POSIX specific.
329139257Sdavidxu    case 'C': k = ConversionSpecifier::CArg; break;
330161678Sdavidxu    case 'S': k = ConversionSpecifier::SArg; break;
331177848Sdavidxu    // Apple extension for os_log
332161678Sdavidxu    case 'P':
333139257Sdavidxu      k = ConversionSpecifier::PArg;
334177848Sdavidxu      break;
335139257Sdavidxu    // Objective-C.
336161678Sdavidxu    case '@': k = ConversionSpecifier::ObjCObjArg; break;
337139257Sdavidxu    // Glibc specific.
338161678Sdavidxu    case 'm': k = ConversionSpecifier::PrintErrno; break;
339177848Sdavidxu    // FreeBSD kernel specific.
340139257Sdavidxu    case 'b':
341139257Sdavidxu      if (isFreeBSDKPrintf)
342161678Sdavidxu        k = ConversionSpecifier::FreeBSDbArg; // int followed by char *
343177848Sdavidxu      break;
344177848Sdavidxu    case 'r':
345161678Sdavidxu      if (isFreeBSDKPrintf)
346139257Sdavidxu        k = ConversionSpecifier::FreeBSDrArg; // int
347177848Sdavidxu      break;
348138224Sdavidxu    case 'y':
349161678Sdavidxu      if (isFreeBSDKPrintf)
350161678Sdavidxu        k = ConversionSpecifier::FreeBSDyArg; // int
351161678Sdavidxu      break;
352177848Sdavidxu    // Apple-specific.
353177848Sdavidxu    case 'D':
354177880Sdavidxu      if (isFreeBSDKPrintf)
355177880Sdavidxu        k = ConversionSpecifier::FreeBSDDArg; // void * followed by char *
356177880Sdavidxu      else if (Target.getTriple().isOSDarwin())
357177880Sdavidxu        k = ConversionSpecifier::DArg;
358177880Sdavidxu      break;
359177880Sdavidxu    case 'O':
360177880Sdavidxu      if (Target.getTriple().isOSDarwin())
361177880Sdavidxu        k = ConversionSpecifier::OArg;
362177880Sdavidxu      break;
363177848Sdavidxu    case 'U':
364177880Sdavidxu      if (Target.getTriple().isOSDarwin())
365177880Sdavidxu        k = ConversionSpecifier::UArg;
366177848Sdavidxu      break;
367177848Sdavidxu    // MS specific.
368177848Sdavidxu    case 'Z':
369177848Sdavidxu      if (Target.getTriple().isOSMSVCRT())
370177848Sdavidxu        k = ConversionSpecifier::ZArg;
371177848Sdavidxu      break;
372138224Sdavidxu  }
373138224Sdavidxu
374161678Sdavidxu  // Check to see if we used the Objective-C modifier flags with
375177848Sdavidxu  // a conversion specifier other than '@'.
376161678Sdavidxu  if (k != ConversionSpecifier::ObjCObjArg &&
377138225Sdavidxu      k != ConversionSpecifier::InvalidSpecifier &&
378177848Sdavidxu      ObjCModifierFlagsStart) {
379138224Sdavidxu    H.HandleObjCFlagsWithNonObjCConversion(ObjCModifierFlagsStart,
380161678Sdavidxu                                           ObjCModifierFlagsEnd + 1,
381161678Sdavidxu                                           conversionPosition);
382161678Sdavidxu    return true;
383177848Sdavidxu  }
384177848Sdavidxu
385177848Sdavidxu  PrintfConversionSpecifier CS(conversionPosition, k);
386177848Sdavidxu  FS.setConversionSpecifier(CS);
387177848Sdavidxu  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
388138224Sdavidxu    FS.setArgIndex(argIndex++);
389138224Sdavidxu  // FreeBSD kernel specific.
390201991Sdavidxu  if (k == ConversionSpecifier::FreeBSDbArg ||
391201991Sdavidxu      k == ConversionSpecifier::FreeBSDDArg)
392201991Sdavidxu    argIndex++;
393201991Sdavidxu
394201991Sdavidxu  if (k == ConversionSpecifier::InvalidSpecifier) {
395201991Sdavidxu    unsigned Len = I - Start;
396201991Sdavidxu    if (ParseUTF8InvalidSpecifier(Start, E, Len)) {
397201991Sdavidxu      CS.setEndScanList(Start + Len);
398201991Sdavidxu      FS.setConversionSpecifier(CS);
399201991Sdavidxu    }
400201991Sdavidxu    // Assume the conversion takes one argument.
401201991Sdavidxu    return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, Len);
402201991Sdavidxu  }
403201991Sdavidxu  return PrintfSpecifierResult(Start, FS);
404201991Sdavidxu}
405201991Sdavidxu
406139013Sdavidxubool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
407177848Sdavidxu                                                     const char *I,
408115765Sjeff                                                     const char *E,
409201991Sdavidxu                                                     const LangOptions &LO,
410161678Sdavidxu                                                     const TargetInfo &Target,
411139013Sdavidxu                                                     bool isFreeBSDKPrintf) {
412161678Sdavidxu
413161678Sdavidxu  unsigned argIndex = 0;
414201991Sdavidxu
415203744Sdavidxu  // Keep looking for a format specifier until we have exhausted the string.
416201991Sdavidxu  while (I != E) {
417201991Sdavidxu    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
418201991Sdavidxu                                                            LO, Target, true,
419201991Sdavidxu                                                            isFreeBSDKPrintf);
420201991Sdavidxu    // Did a fail-stop error of any kind occur when parsing the specifier?
421201991Sdavidxu    // If so, don't do any more processing.
422201991Sdavidxu    if (FSR.shouldStop())
423201991Sdavidxu      return true;
424201991Sdavidxu    // Did we exhaust the string or encounter an error that
425201991Sdavidxu    // we can recover from?
426201991Sdavidxu    if (!FSR.hasValue())
427233045Sdavide      continue;
428233045Sdavide    // We have a format specifier.  Pass it to the callback.
429233045Sdavide    if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
430233045Sdavide                                 I - FSR.getStart()))
431233045Sdavide      return true;
432233045Sdavide  }
433233045Sdavide  assert(I == E && "Format string not exhausted");
434233045Sdavide  return false;
435158718Sdavidxu}
436201991Sdavidxu
437201991Sdavidxubool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
438139013Sdavidxu                                                            const char *E,
439139013Sdavidxu                                                            const LangOptions &LO,
440139013Sdavidxu                                                            const TargetInfo &Target) {
441177848Sdavidxu
442139013Sdavidxu  unsigned argIndex = 0;
443161678Sdavidxu
444201991Sdavidxu  // Keep looking for a %s format specifier until we have exhausted the string.
445161678Sdavidxu  FormatStringHandler H;
446161678Sdavidxu  while (I != E) {
447161678Sdavidxu    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
448158718Sdavidxu                                                            LO, Target, false,
449201991Sdavidxu                                                            false);
450201991Sdavidxu    // Did a fail-stop error of any kind occur when parsing the specifier?
451201991Sdavidxu    // If so, don't do any more processing.
452233045Sdavide    if (FSR.shouldStop())
453233045Sdavide      return false;
454233045Sdavide    // Did we exhaust the string or encounter an error that
455158718Sdavidxu    // we can recover from?
456201991Sdavidxu    if (!FSR.hasValue())
457201991Sdavidxu      continue;
458201991Sdavidxu    const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
459201991Sdavidxu    // Return true if this a %s format specifier.
460201991Sdavidxu    if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
461201991Sdavidxu      return true;
462201991Sdavidxu  }
463201991Sdavidxu  return false;
464201991Sdavidxu}
465201991Sdavidxu
466201991Sdavidxubool clang::analyze_format_string::parseFormatStringHasFormattingSpecifiers(
467139013Sdavidxu    const char *Begin, const char *End, const LangOptions &LO,
468139013Sdavidxu    const TargetInfo &Target) {
469139013Sdavidxu  unsigned ArgIndex = 0;
470161678Sdavidxu  // Keep looking for a formatting specifier until we have exhausted the string.
471161678Sdavidxu  FormatStringHandler H;
472161678Sdavidxu  while (Begin != End) {
473139013Sdavidxu    const PrintfSpecifierResult &FSR =
474139013Sdavidxu        ParsePrintfSpecifier(H, Begin, End, ArgIndex, LO, Target, false, false);
475139013Sdavidxu    if (FSR.shouldStop())
476161678Sdavidxu      break;
477201991Sdavidxu    if (FSR.hasValue())
478115765Sjeff      return true;
479161678Sdavidxu  }
480161678Sdavidxu  return false;
481201991Sdavidxu}
482201991Sdavidxu
483201991Sdavidxu//===----------------------------------------------------------------------===//
484201991Sdavidxu// Methods on PrintfSpecifier.
485115765Sjeff//===----------------------------------------------------------------------===//
486115765Sjeff
487161678SdavidxuArgType PrintfSpecifier::getScalarArgType(ASTContext &Ctx,
488161678Sdavidxu                                          bool IsObjCLiteral) const {
489161678Sdavidxu  if (CS.getKind() == ConversionSpecifier::cArg)
490161678Sdavidxu    switch (LM.getKind()) {
491139257Sdavidxu      case LengthModifier::None:
492161678Sdavidxu        return Ctx.IntTy;
493161678Sdavidxu      case LengthModifier::AsLong:
494161678Sdavidxu      case LengthModifier::AsWide:
495201991Sdavidxu        return ArgType(ArgType::WIntTy, "wint_t");
496161678Sdavidxu      case LengthModifier::AsShort:
497161678Sdavidxu        if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
498161678Sdavidxu          return Ctx.IntTy;
499161678Sdavidxu        LLVM_FALLTHROUGH;
500201991Sdavidxu      default:
501201991Sdavidxu        return ArgType::Invalid();
502201991Sdavidxu    }
503201991Sdavidxu
504161678Sdavidxu  if (CS.isIntArg())
505201991Sdavidxu    switch (LM.getKind()) {
506161678Sdavidxu      case LengthModifier::AsLongDouble:
507161678Sdavidxu        // GNU extension.
508161678Sdavidxu        return Ctx.LongLongTy;
509161678Sdavidxu      case LengthModifier::None:
510161678Sdavidxu      case LengthModifier::AsShortLong:
511177848Sdavidxu        return Ctx.IntTy;
512161678Sdavidxu      case LengthModifier::AsInt32:
513177848Sdavidxu        return ArgType(Ctx.IntTy, "__int32");
514115765Sjeff      case LengthModifier::AsChar:
515161678Sdavidxu        return ArgType::AnyCharTy;
516201991Sdavidxu      case LengthModifier::AsShort: return Ctx.ShortTy;
517201991Sdavidxu      case LengthModifier::AsLong: return Ctx.LongTy;
518161678Sdavidxu      case LengthModifier::AsLongLong:
519115765Sjeff      case LengthModifier::AsQuad:
520139257Sdavidxu        return Ctx.LongLongTy;
521161678Sdavidxu      case LengthModifier::AsInt64:
522161678Sdavidxu        return ArgType(Ctx.LongLongTy, "__int64");
523201991Sdavidxu      case LengthModifier::AsIntMax:
524201991Sdavidxu        return ArgType(Ctx.getIntMaxType(), "intmax_t");
525201991Sdavidxu      case LengthModifier::AsSizeT:
526177848Sdavidxu        return ArgType::makeSizeT(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
527161678Sdavidxu      case LengthModifier::AsInt3264:
528139257Sdavidxu        return Ctx.getTargetInfo().getTriple().isArch64Bit()
529201991Sdavidxu                   ? ArgType(Ctx.LongLongTy, "__int64")
530139013Sdavidxu                   : ArgType(Ctx.IntTy, "__int32");
531139013Sdavidxu      case LengthModifier::AsPtrDiff:
532139257Sdavidxu        return ArgType::makePtrdiffT(
533138224Sdavidxu            ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
534138224Sdavidxu      case LengthModifier::AsAllocate:
535177848Sdavidxu      case LengthModifier::AsMAllocate:
536161678Sdavidxu      case LengthModifier::AsWide:
537161678Sdavidxu        return ArgType::Invalid();
538161678Sdavidxu    }
539161678Sdavidxu
540161678Sdavidxu  if (CS.isUIntArg())
541161678Sdavidxu    switch (LM.getKind()) {
542161678Sdavidxu      case LengthModifier::AsLongDouble:
543161678Sdavidxu        // GNU extension.
544161678Sdavidxu        return Ctx.UnsignedLongLongTy;
545161678Sdavidxu      case LengthModifier::None:
546161678Sdavidxu      case LengthModifier::AsShortLong:
547161678Sdavidxu        return Ctx.UnsignedIntTy;
548161678Sdavidxu      case LengthModifier::AsInt32:
549161678Sdavidxu        return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
550161678Sdavidxu      case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
551161678Sdavidxu      case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
552161678Sdavidxu      case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
553161678Sdavidxu      case LengthModifier::AsLongLong:
554138224Sdavidxu      case LengthModifier::AsQuad:
555161678Sdavidxu        return Ctx.UnsignedLongLongTy;
556138224Sdavidxu      case LengthModifier::AsInt64:
557161678Sdavidxu        return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
558161678Sdavidxu      case LengthModifier::AsIntMax:
559161678Sdavidxu        return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
560161678Sdavidxu      case LengthModifier::AsSizeT:
561161678Sdavidxu        return ArgType::makeSizeT(ArgType(Ctx.getSizeType(), "size_t"));
562161678Sdavidxu      case LengthModifier::AsInt3264:
563161678Sdavidxu        return Ctx.getTargetInfo().getTriple().isArch64Bit()
564161678Sdavidxu                   ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
565139751Sdavidxu                   : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
566139751Sdavidxu      case LengthModifier::AsPtrDiff:
567139751Sdavidxu        return ArgType::makePtrdiffT(
568138224Sdavidxu            ArgType(Ctx.getUnsignedPointerDiffType(), "unsigned ptrdiff_t"));
569138224Sdavidxu      case LengthModifier::AsAllocate:
570161678Sdavidxu      case LengthModifier::AsMAllocate:
571161678Sdavidxu      case LengthModifier::AsWide:
572161678Sdavidxu        return ArgType::Invalid();
573218969Sjhb    }
574161678Sdavidxu
575139013Sdavidxu  if (CS.isDoubleArg()) {
576161678Sdavidxu    if (!VectorNumElts.isInvalid()) {
577139013Sdavidxu      switch (LM.getKind()) {
578139013Sdavidxu      case LengthModifier::AsShort:
579139013Sdavidxu        return Ctx.HalfTy;
580139013Sdavidxu      case LengthModifier::AsShortLong:
581139013Sdavidxu        return Ctx.FloatTy;
582139013Sdavidxu      case LengthModifier::AsLong:
583161678Sdavidxu      default:
584161678Sdavidxu        return Ctx.DoubleTy;
585161678Sdavidxu      }
586161678Sdavidxu    }
587161678Sdavidxu
588163677Sdavidxu    if (LM.getKind() == LengthModifier::AsLongDouble)
589163677Sdavidxu      return Ctx.LongDoubleTy;
590161678Sdavidxu    return Ctx.DoubleTy;
591161678Sdavidxu  }
592161678Sdavidxu
593161678Sdavidxu  if (CS.getKind() == ConversionSpecifier::nArg) {
594161678Sdavidxu    switch (LM.getKind()) {
595161678Sdavidxu      case LengthModifier::None:
596161678Sdavidxu        return ArgType::PtrTo(Ctx.IntTy);
597161678Sdavidxu      case LengthModifier::AsChar:
598161678Sdavidxu        return ArgType::PtrTo(Ctx.SignedCharTy);
599161678Sdavidxu      case LengthModifier::AsShort:
600161678Sdavidxu        return ArgType::PtrTo(Ctx.ShortTy);
601161678Sdavidxu      case LengthModifier::AsLong:
602161678Sdavidxu        return ArgType::PtrTo(Ctx.LongTy);
603161678Sdavidxu      case LengthModifier::AsLongLong:
604161678Sdavidxu      case LengthModifier::AsQuad:
605161678Sdavidxu        return ArgType::PtrTo(Ctx.LongLongTy);
606161678Sdavidxu      case LengthModifier::AsIntMax:
607161678Sdavidxu        return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
608161678Sdavidxu      case LengthModifier::AsSizeT:
609161678Sdavidxu        return ArgType::PtrTo(ArgType(Ctx.getSignedSizeType(), "ssize_t"));
610139013Sdavidxu      case LengthModifier::AsPtrDiff:
611139013Sdavidxu        return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
612161678Sdavidxu      case LengthModifier::AsLongDouble:
613139013Sdavidxu        return ArgType(); // FIXME: Is this a known extension?
614139013Sdavidxu      case LengthModifier::AsAllocate:
615139013Sdavidxu      case LengthModifier::AsMAllocate:
616161678Sdavidxu      case LengthModifier::AsInt32:
617161678Sdavidxu      case LengthModifier::AsInt3264:
618161678Sdavidxu      case LengthModifier::AsInt64:
619218969Sjhb      case LengthModifier::AsWide:
620139013Sdavidxu        return ArgType::Invalid();
621139013Sdavidxu      case LengthModifier::AsShortLong:
622161678Sdavidxu        llvm_unreachable("only used for OpenCL which doesn not handle nArg");
623139013Sdavidxu    }
624139013Sdavidxu  }
625139013Sdavidxu
626161678Sdavidxu  switch (CS.getKind()) {
627161678Sdavidxu    case ConversionSpecifier::sArg:
628161678Sdavidxu      if (LM.getKind() == LengthModifier::AsWideChar) {
629139013Sdavidxu        if (IsObjCLiteral)
630163449Sdavidxu          return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
631112904Sjeff                         "const unichar *");
632143149Sdavidxu        return ArgType(ArgType::WCStrTy, "wchar_t *");
633163449Sdavidxu      }
634163449Sdavidxu      if (LM.getKind() == LengthModifier::AsWide)
635138224Sdavidxu        return ArgType(ArgType::WCStrTy, "wchar_t *");
636112904Sjeff      return ArgType::CStrTy;
637143149Sdavidxu    case ConversionSpecifier::SArg:
638161678Sdavidxu      if (IsObjCLiteral)
639112904Sjeff        return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
640161678Sdavidxu                       "const unichar *");
641112904Sjeff      if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
642112904Sjeff          LM.getKind() == LengthModifier::AsShort)
643112904Sjeff        return ArgType::CStrTy;
644112904Sjeff      return ArgType(ArgType::WCStrTy, "wchar_t *");
645112904Sjeff    case ConversionSpecifier::CArg:
646112904Sjeff      if (IsObjCLiteral)
647163449Sdavidxu        return ArgType(Ctx.UnsignedShortTy, "unichar");
648112904Sjeff      if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
649138224Sdavidxu          LM.getKind() == LengthModifier::AsShort)
650138224Sdavidxu        return Ctx.IntTy;
651138224Sdavidxu      return ArgType(Ctx.WideCharTy, "wchar_t");
652138224Sdavidxu    case ConversionSpecifier::pArg:
653115765Sjeff    case ConversionSpecifier::PArg:
654115765Sjeff      return ArgType::CPointerTy;
655115765Sjeff    case ConversionSpecifier::ObjCObjArg:
656115765Sjeff      return ArgType::ObjCPointerTy;
657115765Sjeff    default:
658115765Sjeff      break;
659163449Sdavidxu  }
660139013Sdavidxu
661115765Sjeff  // FIXME: Handle other cases.
662138224Sdavidxu  return ArgType();
663138224Sdavidxu}
664138224Sdavidxu
665115765Sjeff
666115765SjeffArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
667115765Sjeff                                    bool IsObjCLiteral) const {
668115765Sjeff  const PrintfConversionSpecifier &CS = getConversionSpecifier();
669115765Sjeff
670115765Sjeff  if (!CS.consumesDataArgument())
671112904Sjeff    return ArgType::Invalid();
672112904Sjeff
673138224Sdavidxu  ArgType ScalarTy = getScalarArgType(Ctx, IsObjCLiteral);
674138224Sdavidxu  if (!ScalarTy.isValid() || VectorNumElts.isInvalid())
675138224Sdavidxu    return ScalarTy;
676138224Sdavidxu
677161678Sdavidxu  return ScalarTy.makeVectorType(Ctx, VectorNumElts.getConstantAmount());
678138224Sdavidxu}
679112904Sjeff
680161678Sdavidxubool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
681161678Sdavidxu                              ASTContext &Ctx, bool IsObjCLiteral) {
682161678Sdavidxu  // %n is different from other conversion specifiers; don't try to fix it.
683161678Sdavidxu  if (CS.getKind() == ConversionSpecifier::nArg)
684161678Sdavidxu    return false;
685161678Sdavidxu
686161678Sdavidxu  // Handle Objective-C objects first. Note that while the '%@' specifier will
687161678Sdavidxu  // not warn for structure pointer or void pointer arguments (because that's
688161678Sdavidxu  // how CoreFoundation objects are implemented), we only show a fixit for '%@'
689161678Sdavidxu  // if we know it's an object (block, id, class, or __attribute__((NSObject))).
690112904Sjeff  if (QT->isObjCRetainableType()) {
691112904Sjeff    if (!IsObjCLiteral)
692112904Sjeff      return false;
693112904Sjeff
694112904Sjeff    CS.setKind(ConversionSpecifier::ObjCObjArg);
695112904Sjeff
696163449Sdavidxu    // Disable irrelevant flags
697112904Sjeff    HasThousandsGrouping = false;
698112904Sjeff    HasPlusPrefix = false;
699112967Sjake    HasSpacePrefix = false;
700143149Sdavidxu    HasAlternativeForm = false;
701143149Sdavidxu    HasLeadingZeroes = false;
702143149Sdavidxu    Precision.setHowSpecified(OptionalAmount::NotSpecified);
703143149Sdavidxu    LM.setKind(LengthModifier::None);
704115765Sjeff
705112904Sjeff    return true;
706112904Sjeff  }
707112904Sjeff
708115765Sjeff  // Handle strings next (char *, wchar_t *)
709117685Smtm  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
710117685Smtm    CS.setKind(ConversionSpecifier::sArg);
711112904Sjeff
712143149Sdavidxu    // Disable irrelevant flags
713161678Sdavidxu    HasAlternativeForm = 0;
714161678Sdavidxu    HasLeadingZeroes = 0;
715143149Sdavidxu
716143149Sdavidxu    // Set the long length modifier for wide characters
717143149Sdavidxu    if (QT->getPointeeType()->isWideCharType())
718112904Sjeff      LM.setKind(LengthModifier::AsWideChar);
719117743Smtm    else
720117743Smtm      LM.setKind(LengthModifier::None);
721112904Sjeff
722112904Sjeff    return true;
723161678Sdavidxu  }
724161678Sdavidxu
725161678Sdavidxu  // If it's an enum, get its underlying type.
726139013Sdavidxu  if (const EnumType *ETy = QT->getAs<EnumType>())
727163449Sdavidxu    QT = ETy->getDecl()->getIntegerType();
728140245Sdavidxu
729112904Sjeff  const BuiltinType *BT = QT->getAs<BuiltinType>();
730140245Sdavidxu  if (!BT) {
731139013Sdavidxu    const VectorType *VT = QT->getAs<VectorType>();
732140245Sdavidxu    if (VT) {
733139013Sdavidxu      QT = VT->getElementType();
734140245Sdavidxu      BT = QT->getAs<BuiltinType>();
735162536Sdavidxu      VectorNumElts = OptionalAmount(VT->getNumElements());
736162030Sdavidxu    }
737162030Sdavidxu  }
738162030Sdavidxu
739139013Sdavidxu  // We can only work with builtin types.
740140245Sdavidxu  if (!BT)
741140245Sdavidxu    return false;
742140245Sdavidxu
743139013Sdavidxu  // Set length modifier
744162536Sdavidxu  switch (BT->getKind()) {
745140245Sdavidxu  case BuiltinType::Bool:
746140245Sdavidxu  case BuiltinType::WChar_U:
747140245Sdavidxu  case BuiltinType::WChar_S:
748140245Sdavidxu  case BuiltinType::Char8: // FIXME: Treat like 'char'?
749139751Sdavidxu  case BuiltinType::Char16:
750139013Sdavidxu  case BuiltinType::Char32:
751139013Sdavidxu  case BuiltinType::UInt128:
752140245Sdavidxu  case BuiltinType::Int128:
753140245Sdavidxu  case BuiltinType::Half:
754140245Sdavidxu  case BuiltinType::Float16:
755139013Sdavidxu  case BuiltinType::Float128:
756162030Sdavidxu  case BuiltinType::ShortAccum:
757162030Sdavidxu  case BuiltinType::Accum:
758162030Sdavidxu  case BuiltinType::LongAccum:
759139013Sdavidxu  case BuiltinType::UShortAccum:
760139013Sdavidxu  case BuiltinType::UAccum:
761139013Sdavidxu  case BuiltinType::ULongAccum:
762139013Sdavidxu  case BuiltinType::ShortFract:
763161678Sdavidxu  case BuiltinType::Fract:
764161678Sdavidxu  case BuiltinType::LongFract:
765161678Sdavidxu  case BuiltinType::UShortFract:
766139013Sdavidxu  case BuiltinType::UFract:
767163449Sdavidxu  case BuiltinType::ULongFract:
768139013Sdavidxu  case BuiltinType::SatShortAccum:
769139013Sdavidxu  case BuiltinType::SatAccum:
770163449Sdavidxu  case BuiltinType::SatLongAccum:
771163449Sdavidxu  case BuiltinType::SatUShortAccum:
772139257Sdavidxu  case BuiltinType::SatUAccum:
773139257Sdavidxu  case BuiltinType::SatULongAccum:
774112904Sjeff  case BuiltinType::SatShortFract:
775112904Sjeff  case BuiltinType::SatFract:
776112904Sjeff  case BuiltinType::SatLongFract:
777112904Sjeff  case BuiltinType::SatUShortFract:
778163449Sdavidxu  case BuiltinType::SatUFract:
779161678Sdavidxu  case BuiltinType::SatULongFract:
780115765Sjeff    // Various types which are non-trivial to correct.
781115765Sjeff    return false;
782139013Sdavidxu
783115765Sjeff#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
784112904Sjeff  case BuiltinType::Id:
785161678Sdavidxu#include "clang/Basic/OpenCLImageTypes.def"
786161678Sdavidxu#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
787163449Sdavidxu  case BuiltinType::Id:
788161678Sdavidxu#include "clang/Basic/OpenCLExtensionTypes.def"
789161678Sdavidxu#define SVE_TYPE(Name, Id, SingletonId) \
790161678Sdavidxu  case BuiltinType::Id:
791161678Sdavidxu#include "clang/Basic/AArch64SVEACLETypes.def"
792161855Sdavidxu#define SIGNED_TYPE(Id, SingletonId)
793161678Sdavidxu#define UNSIGNED_TYPE(Id, SingletonId)
794161678Sdavidxu#define FLOATING_TYPE(Id, SingletonId)
795117685Smtm#define BUILTIN_TYPE(Id, SingletonId) \
796161678Sdavidxu  case BuiltinType::Id:
797161678Sdavidxu#include "clang/AST/BuiltinTypes.def"
798139257Sdavidxu    // Misc other stuff which doesn't make sense here.
799139257Sdavidxu    return false;
800139257Sdavidxu
801139257Sdavidxu  case BuiltinType::UInt:
802139257Sdavidxu  case BuiltinType::Int:
803139257Sdavidxu  case BuiltinType::Float:
804139257Sdavidxu    LM.setKind(VectorNumElts.isInvalid() ?
805117743Smtm               LengthModifier::None : LengthModifier::AsShortLong);
806117743Smtm    break;
807117743Smtm  case BuiltinType::Double:
808117743Smtm    LM.setKind(VectorNumElts.isInvalid() ?
809117743Smtm               LengthModifier::None : LengthModifier::AsLong);
810163449Sdavidxu    break;
811163449Sdavidxu  case BuiltinType::Char_U:
812139257Sdavidxu  case BuiltinType::UChar:
813161678Sdavidxu  case BuiltinType::Char_S:
814139257Sdavidxu  case BuiltinType::SChar:
815139257Sdavidxu    LM.setKind(LengthModifier::AsChar);
816139257Sdavidxu    break;
817115765Sjeff
818115765Sjeff  case BuiltinType::Short:
819138224Sdavidxu  case BuiltinType::UShort:
820138224Sdavidxu    LM.setKind(LengthModifier::AsShort);
821115765Sjeff    break;
822112904Sjeff
823139013Sdavidxu  case BuiltinType::Long:
824205014Snwhitehorn  case BuiltinType::ULong:
825162536Sdavidxu    LM.setKind(LengthModifier::AsLong);
826161678Sdavidxu    break;
827162536Sdavidxu
828162536Sdavidxu  case BuiltinType::LongLong:
829162536Sdavidxu  case BuiltinType::ULongLong:
830162536Sdavidxu    LM.setKind(LengthModifier::AsLongLong);
831162536Sdavidxu    break;
832162536Sdavidxu
833162536Sdavidxu  case BuiltinType::LongDouble:
834162536Sdavidxu    LM.setKind(LengthModifier::AsLongDouble);
835162536Sdavidxu    break;
836162536Sdavidxu  }
837162536Sdavidxu
838162536Sdavidxu  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
839162536Sdavidxu  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
840162536Sdavidxu    namedTypeToLengthModifier(QT, LM);
841162536Sdavidxu
842162536Sdavidxu  // If fixing the length modifier was enough, we might be done.
843162536Sdavidxu  if (hasValidLengthModifier(Ctx.getTargetInfo(), LangOpt)) {
844162536Sdavidxu    // If we're going to offer a fix anyway, make sure the sign matches.
845162536Sdavidxu    switch (CS.getKind()) {
846162536Sdavidxu    case ConversionSpecifier::uArg:
847162536Sdavidxu    case ConversionSpecifier::UArg:
848162536Sdavidxu      if (QT->isSignedIntegerType())
849162536Sdavidxu        CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
850162536Sdavidxu      break;
851162536Sdavidxu    case ConversionSpecifier::dArg:
852162536Sdavidxu    case ConversionSpecifier::DArg:
853162536Sdavidxu    case ConversionSpecifier::iArg:
854162536Sdavidxu      if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
855162536Sdavidxu        CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
856162536Sdavidxu      break;
857162536Sdavidxu    default:
858162536Sdavidxu      // Other specifiers do not have signed/unsigned variants.
859162536Sdavidxu      break;
860162536Sdavidxu    }
861162536Sdavidxu
862162536Sdavidxu    const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
863162536Sdavidxu    if (ATR.isValid() && ATR.matchesType(Ctx, QT))
864162536Sdavidxu      return true;
865162536Sdavidxu  }
866162536Sdavidxu
867162536Sdavidxu  // Set conversion specifier and disable any flags which do not apply to it.
868162536Sdavidxu  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
869162536Sdavidxu  if (!isa<TypedefType>(QT) && QT->isCharType()) {
870162536Sdavidxu    CS.setKind(ConversionSpecifier::cArg);
871162536Sdavidxu    LM.setKind(LengthModifier::None);
872162536Sdavidxu    Precision.setHowSpecified(OptionalAmount::NotSpecified);
873162536Sdavidxu    HasAlternativeForm = 0;
874162536Sdavidxu    HasLeadingZeroes = 0;
875162536Sdavidxu    HasPlusPrefix = 0;
876162536Sdavidxu  }
877162536Sdavidxu  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
878162536Sdavidxu  else if (QT->isRealFloatingType()) {
879162536Sdavidxu    CS.setKind(ConversionSpecifier::fArg);
880162536Sdavidxu  }
881162536Sdavidxu  else if (QT->isSignedIntegerType()) {
882162536Sdavidxu    CS.setKind(ConversionSpecifier::dArg);
883162536Sdavidxu    HasAlternativeForm = 0;
884162536Sdavidxu  }
885162536Sdavidxu  else if (QT->isUnsignedIntegerType()) {
886162536Sdavidxu    CS.setKind(ConversionSpecifier::uArg);
887162536Sdavidxu    HasAlternativeForm = 0;
888162536Sdavidxu    HasPlusPrefix = 0;
889162536Sdavidxu  } else {
890162536Sdavidxu    llvm_unreachable("Unexpected type");
891162536Sdavidxu  }
892162536Sdavidxu
893162536Sdavidxu  return true;
894162536Sdavidxu}
895162536Sdavidxu
896162536Sdavidxuvoid PrintfSpecifier::toString(raw_ostream &os) const {
897162536Sdavidxu  // Whilst some features have no defined order, we are using the order
898162536Sdavidxu  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
899162536Sdavidxu  os << "%";
900162536Sdavidxu
901162536Sdavidxu  // Positional args
902162536Sdavidxu  if (usesPositionalArg()) {
903162536Sdavidxu    os << getPositionalArgIndex() << "$";
904162536Sdavidxu  }
905162536Sdavidxu
906162536Sdavidxu  // Conversion flags
907162536Sdavidxu  if (IsLeftJustified)    os << "-";
908162536Sdavidxu  if (HasPlusPrefix)      os << "+";
909162536Sdavidxu  if (HasSpacePrefix)     os << " ";
910162536Sdavidxu  if (HasAlternativeForm) os << "#";
911162536Sdavidxu  if (HasLeadingZeroes)   os << "0";
912162536Sdavidxu
913162536Sdavidxu  // Minimum field width
914162536Sdavidxu  FieldWidth.toString(os);
915162536Sdavidxu  // Precision
916162536Sdavidxu  Precision.toString(os);
917162536Sdavidxu
918162536Sdavidxu  // Vector modifier
919162536Sdavidxu  if (!VectorNumElts.isInvalid())
920162536Sdavidxu    os << 'v' << VectorNumElts.getConstantAmount();
921162536Sdavidxu
922162536Sdavidxu  // Length modifier
923162536Sdavidxu  os << LM.toString();
924162536Sdavidxu  // Conversion specifier
925162536Sdavidxu  os << CS.toString();
926162536Sdavidxu}
927162536Sdavidxu
928162536Sdavidxubool PrintfSpecifier::hasValidPlusPrefix() const {
929162536Sdavidxu  if (!HasPlusPrefix)
930162536Sdavidxu    return true;
931162536Sdavidxu
932162536Sdavidxu  // The plus prefix only makes sense for signed conversions
933162536Sdavidxu  switch (CS.getKind()) {
934162536Sdavidxu  case ConversionSpecifier::dArg:
935162536Sdavidxu  case ConversionSpecifier::DArg:
936162536Sdavidxu  case ConversionSpecifier::iArg:
937162536Sdavidxu  case ConversionSpecifier::fArg:
938162536Sdavidxu  case ConversionSpecifier::FArg:
939162536Sdavidxu  case ConversionSpecifier::eArg:
940162536Sdavidxu  case ConversionSpecifier::EArg:
941162536Sdavidxu  case ConversionSpecifier::gArg:
942162536Sdavidxu  case ConversionSpecifier::GArg:
943162536Sdavidxu  case ConversionSpecifier::aArg:
944162536Sdavidxu  case ConversionSpecifier::AArg:
945162536Sdavidxu  case ConversionSpecifier::FreeBSDrArg:
946162536Sdavidxu  case ConversionSpecifier::FreeBSDyArg:
947162536Sdavidxu    return true;
948162536Sdavidxu
949162536Sdavidxu  default:
950162536Sdavidxu    return false;
951162536Sdavidxu  }
952162536Sdavidxu}
953162536Sdavidxu
954162536Sdavidxubool PrintfSpecifier::hasValidAlternativeForm() const {
955162536Sdavidxu  if (!HasAlternativeForm)
956162536Sdavidxu    return true;
957162536Sdavidxu
958162536Sdavidxu  // Alternate form flag only valid with the oxXaAeEfFgG conversions
959162536Sdavidxu  switch (CS.getKind()) {
960162536Sdavidxu  case ConversionSpecifier::oArg:
961162536Sdavidxu  case ConversionSpecifier::OArg:
962162536Sdavidxu  case ConversionSpecifier::xArg:
963162536Sdavidxu  case ConversionSpecifier::XArg:
964162536Sdavidxu  case ConversionSpecifier::aArg:
965162536Sdavidxu  case ConversionSpecifier::AArg:
966162536Sdavidxu  case ConversionSpecifier::eArg:
967162536Sdavidxu  case ConversionSpecifier::EArg:
968162536Sdavidxu  case ConversionSpecifier::fArg:
969162536Sdavidxu  case ConversionSpecifier::FArg:
970162536Sdavidxu  case ConversionSpecifier::gArg:
971162536Sdavidxu  case ConversionSpecifier::GArg:
972162536Sdavidxu  case ConversionSpecifier::FreeBSDrArg:
973162536Sdavidxu  case ConversionSpecifier::FreeBSDyArg:
974162536Sdavidxu    return true;
975162536Sdavidxu
976162536Sdavidxu  default:
977162536Sdavidxu    return false;
978162536Sdavidxu  }
979162536Sdavidxu}
980162536Sdavidxu
981162536Sdavidxubool PrintfSpecifier::hasValidLeadingZeros() const {
982162536Sdavidxu  if (!HasLeadingZeroes)
983162536Sdavidxu    return true;
984162536Sdavidxu
985162536Sdavidxu  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
986162536Sdavidxu  switch (CS.getKind()) {
987162536Sdavidxu  case ConversionSpecifier::dArg:
988162536Sdavidxu  case ConversionSpecifier::DArg:
989162536Sdavidxu  case ConversionSpecifier::iArg:
990162536Sdavidxu  case ConversionSpecifier::oArg:
991162536Sdavidxu  case ConversionSpecifier::OArg:
992162536Sdavidxu  case ConversionSpecifier::uArg:
993162536Sdavidxu  case ConversionSpecifier::UArg:
994162536Sdavidxu  case ConversionSpecifier::xArg:
995162536Sdavidxu  case ConversionSpecifier::XArg:
996162536Sdavidxu  case ConversionSpecifier::aArg:
997162536Sdavidxu  case ConversionSpecifier::AArg:
998162536Sdavidxu  case ConversionSpecifier::eArg:
999162536Sdavidxu  case ConversionSpecifier::EArg:
1000162536Sdavidxu  case ConversionSpecifier::fArg:
1001162536Sdavidxu  case ConversionSpecifier::FArg:
1002162536Sdavidxu  case ConversionSpecifier::gArg:
1003162536Sdavidxu  case ConversionSpecifier::GArg:
1004162536Sdavidxu  case ConversionSpecifier::FreeBSDrArg:
1005162536Sdavidxu  case ConversionSpecifier::FreeBSDyArg:
1006162536Sdavidxu    return true;
1007162536Sdavidxu
1008162536Sdavidxu  default:
1009162536Sdavidxu    return false;
1010162536Sdavidxu  }
1011162536Sdavidxu}
1012162536Sdavidxu
1013162536Sdavidxubool PrintfSpecifier::hasValidSpacePrefix() const {
1014162536Sdavidxu  if (!HasSpacePrefix)
1015162536Sdavidxu    return true;
1016162536Sdavidxu
1017162536Sdavidxu  // The space prefix only makes sense for signed conversions
1018162536Sdavidxu  switch (CS.getKind()) {
1019162536Sdavidxu  case ConversionSpecifier::dArg:
1020162536Sdavidxu  case ConversionSpecifier::DArg:
1021162536Sdavidxu  case ConversionSpecifier::iArg:
1022162536Sdavidxu  case ConversionSpecifier::fArg:
1023162536Sdavidxu  case ConversionSpecifier::FArg:
1024231989Sdavidxu  case ConversionSpecifier::eArg:
1025231989Sdavidxu  case ConversionSpecifier::EArg:
1026231989Sdavidxu  case ConversionSpecifier::gArg:
1027231989Sdavidxu  case ConversionSpecifier::GArg:
1028231989Sdavidxu  case ConversionSpecifier::aArg:
1029231989Sdavidxu  case ConversionSpecifier::AArg:
1030231989Sdavidxu  case ConversionSpecifier::FreeBSDrArg:
1031231989Sdavidxu  case ConversionSpecifier::FreeBSDyArg:
1032231989Sdavidxu    return true;
1033162536Sdavidxu
1034161678Sdavidxu  default:
1035161678Sdavidxu    return false;
1036139013Sdavidxu  }
1037163449Sdavidxu}
1038232144Sdavidxu
1039139013Sdavidxubool PrintfSpecifier::hasValidLeftJustified() const {
1040143149Sdavidxu  if (!IsLeftJustified)
1041231989Sdavidxu    return true;
1042163449Sdavidxu
1043140245Sdavidxu  // The left justified flag is valid for all conversions except n
1044139013Sdavidxu  switch (CS.getKind()) {
1045143149Sdavidxu  case ConversionSpecifier::nArg:
1046178646Sdavidxu    return false;
1047178646Sdavidxu
1048139013Sdavidxu  default:
1049161678Sdavidxu    return true;
1050161678Sdavidxu  }
1051161678Sdavidxu}
1052161678Sdavidxu
1053162536Sdavidxubool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
1054162536Sdavidxu  if (!HasThousandsGrouping)
1055162536Sdavidxu    return true;
1056190987Sdavidxu
1057139427Sdavidxu  switch (CS.getKind()) {
1058143149Sdavidxu    case ConversionSpecifier::dArg:
1059143149Sdavidxu    case ConversionSpecifier::DArg:
1060143149Sdavidxu    case ConversionSpecifier::iArg:
1061140245Sdavidxu    case ConversionSpecifier::uArg:
1062143149Sdavidxu    case ConversionSpecifier::UArg:
1063164839Sdavidxu    case ConversionSpecifier::fArg:
1064161678Sdavidxu    case ConversionSpecifier::FArg:
1065143149Sdavidxu    case ConversionSpecifier::gArg:
1066139013Sdavidxu    case ConversionSpecifier::GArg:
1067232144Sdavidxu      return true;
1068232144Sdavidxu    default:
1069231989Sdavidxu      return false;
1070232144Sdavidxu  }
1071231989Sdavidxu}
1072232144Sdavidxu
1073231989Sdavidxubool PrintfSpecifier::hasValidPrecision() const {
1074161678Sdavidxu  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
1075139013Sdavidxu    return true;
1076231989Sdavidxu
1077231989Sdavidxu  // Precision is only valid with the diouxXaAeEfFgGsP conversions
1078231989Sdavidxu  switch (CS.getKind()) {
1079231989Sdavidxu  case ConversionSpecifier::dArg:
1080231989Sdavidxu  case ConversionSpecifier::DArg:
1081231989Sdavidxu  case ConversionSpecifier::iArg:
1082231989Sdavidxu  case ConversionSpecifier::oArg:
1083211794Sdavidxu  case ConversionSpecifier::OArg:
1084211794Sdavidxu  case ConversionSpecifier::uArg:
1085161678Sdavidxu  case ConversionSpecifier::UArg:
1086211794Sdavidxu  case ConversionSpecifier::xArg:
1087140245Sdavidxu  case ConversionSpecifier::XArg:
1088140245Sdavidxu  case ConversionSpecifier::aArg:
1089161678Sdavidxu  case ConversionSpecifier::AArg:
1090232144Sdavidxu  case ConversionSpecifier::eArg:
1091161678Sdavidxu  case ConversionSpecifier::EArg:
1092139013Sdavidxu  case ConversionSpecifier::fArg:
1093143149Sdavidxu  case ConversionSpecifier::FArg:
1094143149Sdavidxu  case ConversionSpecifier::gArg:
1095139013Sdavidxu  case ConversionSpecifier::GArg:
1096143149Sdavidxu  case ConversionSpecifier::sArg:
1097139257Sdavidxu  case ConversionSpecifier::FreeBSDrArg:
1098139257Sdavidxu  case ConversionSpecifier::FreeBSDyArg:
1099139013Sdavidxu  case ConversionSpecifier::PArg:
1100139013Sdavidxu    return true;
1101139013Sdavidxu
1102161678Sdavidxu  default:
1103161678Sdavidxu    return false;
1104161678Sdavidxu  }
1105151692Sdavidxu}
1106178646Sdavidxubool PrintfSpecifier::hasValidFieldWidth() const {
1107139013Sdavidxu  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
1108139013Sdavidxu      return true;
1109139257Sdavidxu
1110139013Sdavidxu  // The field width is valid for all conversions except n
1111178646Sdavidxu  switch (CS.getKind()) {
1112178646Sdavidxu  case ConversionSpecifier::nArg:
1113139257Sdavidxu    return false;
1114139258Sdavidxu
1115139257Sdavidxu  default:
1116139258Sdavidxu    return true;
1117139257Sdavidxu  }
1118139013Sdavidxu}
1119139013Sdavidxu