PrintfFormatString.cpp revision 6ca4a9ae99d65948e578d3e7d1f58ab6a947d2d7
112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//
312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//                     The LLVM Compiler Infrastructure
412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//
512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala// This file is distributed under the University of Illinois Open Source
612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala// License. See LICENSE.TXT for details.
712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//
812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//===----------------------------------------------------------------------===//
912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//
1012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala// Handling of format string in printf and friends.  The structure of format
1112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala// strings for fprintf() are described in C99 7.19.6.1.
1212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//
1312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//===----------------------------------------------------------------------===//
1412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
1512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala#include "clang/Analysis/Analyses/FormatString.h"
1612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala#include "FormatStringParsing.h"
1712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
1812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialausing clang::analyze_format_string::ArgTypeResult;
1912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialausing clang::analyze_format_string::FormatStringHandler;
2012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialausing clang::analyze_format_string::LengthModifier;
2112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialausing clang::analyze_format_string::OptionalAmount;
2212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialausing clang::analyze_format_string::ConversionSpecifier;
2312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialausing clang::analyze_printf::PrintfSpecifier;
2412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
2512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialausing namespace clang;
2612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
2712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialatypedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
2812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        PrintfSpecifierResult;
2912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
3012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//===----------------------------------------------------------------------===//
3112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala// Methods for parsing format strings.
3212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//===----------------------------------------------------------------------===//
3312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
3412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialausing analyze_format_string::ParseNonPositionAmount;
3512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
3612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialastatic bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
3712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                           const char *Start, const char *&Beg, const char *E,
3812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                           unsigned *argIndex) {
3912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (argIndex) {
4012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
4112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  } else {
4212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
4312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                                           analyze_format_string::PrecisionPos);
4412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (Amt.isInvalid())
4512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return true;
4612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    FS.setPrecision(Amt);
4712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
4812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  return false;
4912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala}
5012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
5112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialastatic PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
5212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                                                  const char *&Beg,
5312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                                                  const char *E,
5412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                                                  unsigned &argIndex) {
5512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
5612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  using namespace clang::analyze_format_string;
5712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  using namespace clang::analyze_printf;
5812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
5912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  const char *I = Beg;
6012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  const char *Start = 0;
6112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  UpdateOnReturn <const char*> UpdateBeg(Beg, I);
6212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
6312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // Look for a '%' character that indicates the start of a format specifier.
6412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  for ( ; I != E ; ++I) {
6512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    char c = *I;
6612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (c == '\0') {
6712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      // Detect spurious null characters, which are likely errors.
6812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      H.HandleNullChar(I);
6912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return true;
7012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    }
7112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (c == '%') {
7212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      Start = I++;  // Record the start of the format specifier.
7312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      break;
7412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    }
7512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
7612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
7712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // No format specifier found?
7812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (!Start)
7912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return false;
8012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
8112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (I == E) {
8212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // No more characters left?
8312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    H.HandleIncompleteSpecifier(Start, E - Start);
8412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return true;
8512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
8612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
8712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  PrintfSpecifier FS;
8812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (ParseArgPosition(H, FS, Start, I, E))
8912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return true;
9012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
9112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (I == E) {
9212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // No more characters left?
9312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    H.HandleIncompleteSpecifier(Start, E - Start);
9412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return true;
9512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
9612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
9712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // Look for flags (if any).
9812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  bool hasMore = true;
9912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  for ( ; I != E; ++I) {
10012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    switch (*I) {
10112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      default: hasMore = false; break;
10212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case '\'':
10312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        // FIXME: POSIX specific.  Always accept?
10412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        FS.setHasThousandsGrouping(I);
10512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        break;
10612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case '-': FS.setIsLeftJustified(I); break;
10712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case '+': FS.setHasPlusPrefix(I); break;
10812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case ' ': FS.setHasSpacePrefix(I); break;
10912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case '#': FS.setHasAlternativeForm(I); break;
11012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case '0': FS.setHasLeadingZeros(I); break;
11112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    }
11212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (!hasMore)
11312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      break;
11412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
11512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
11612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (I == E) {
11712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // No more characters left?
11812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    H.HandleIncompleteSpecifier(Start, E - Start);
11912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return true;
12012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
12112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
12212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // Look for the field width (if any).
12312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (ParseFieldWidth(H, FS, Start, I, E,
12412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                      FS.usesPositionalArg() ? 0 : &argIndex))
12512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return true;
12612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
12712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (I == E) {
12812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // No more characters left?
12912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    H.HandleIncompleteSpecifier(Start, E - Start);
13012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return true;
13112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
13212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
13312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // Look for the precision (if any).
13412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (*I == '.') {
13512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    ++I;
13612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (I == E) {
13712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      H.HandleIncompleteSpecifier(Start, E - Start);
13812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return true;
13912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    }
14012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
14112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (ParsePrecision(H, FS, Start, I, E,
14212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                       FS.usesPositionalArg() ? 0 : &argIndex))
14312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return true;
14412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
14512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (I == E) {
14612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      // No more characters left?
14712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      H.HandleIncompleteSpecifier(Start, E - Start);
14812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return true;
14912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    }
15012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
15112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
15212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // Look for the length modifier.
15312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (ParseLengthModifier(FS, I, E) && I == E) {
15412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // No more characters left?
15512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    H.HandleIncompleteSpecifier(Start, E - Start);
15612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return true;
15712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
15812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
15912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (*I == '\0') {
16012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // Detect spurious null characters, which are likely errors.
16112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    H.HandleNullChar(I);
16212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return true;
16312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
16412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
16512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // Finally, look for the conversion specifier.
16612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  const char *conversionPosition = I++;
16712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
16812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  switch (*conversionPosition) {
16912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    default:
17012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      break;
17112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // C99: 7.19.6.1 (section 8).
17212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case '%': k = ConversionSpecifier::PercentArg;   break;
17312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'A': k = ConversionSpecifier::AArg; break;
17412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'E': k = ConversionSpecifier::EArg; break;
17512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'F': k = ConversionSpecifier::FArg; break;
17612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'G': k = ConversionSpecifier::GArg; break;
17712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'X': k = ConversionSpecifier::XArg; break;
17812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'a': k = ConversionSpecifier::aArg; break;
17912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'c': k = ConversionSpecifier::cArg; break;
18012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'd': k = ConversionSpecifier::dArg; break;
18112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'e': k = ConversionSpecifier::eArg; break;
18212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'f': k = ConversionSpecifier::fArg; break;
18312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'g': k = ConversionSpecifier::gArg; break;
18412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'i': k = ConversionSpecifier::iArg; break;
18512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'n': k = ConversionSpecifier::nArg; break;
18612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'o': k = ConversionSpecifier::oArg; break;
18712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'p': k = ConversionSpecifier::pArg;   break;
18812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 's': k = ConversionSpecifier::sArg;      break;
18912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'u': k = ConversionSpecifier::uArg; break;
19012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'x': k = ConversionSpecifier::xArg; break;
19112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // POSIX specific.
19212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'C': k = ConversionSpecifier::CArg; break;
19312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'S': k = ConversionSpecifier::SArg; break;
19412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // Objective-C.
19512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case '@': k = ConversionSpecifier::ObjCObjArg; break;
19612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // Glibc specific.
19712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case 'm': k = ConversionSpecifier::PrintErrno; break;
19812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
19912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  PrintfConversionSpecifier CS(conversionPosition, k);
20012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  FS.setConversionSpecifier(CS);
20112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (CS.consumesDataArgument() && !FS.usesPositionalArg())
20212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    FS.setArgIndex(argIndex++);
20312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
20412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (k == ConversionSpecifier::InvalidSpecifier) {
20512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // Assume the conversion takes one argument.
20612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
20712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
20812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  return PrintfSpecifierResult(Start, FS);
20912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala}
21012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
21112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialabool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
21212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                                                     const char *I,
21312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                                                     const char *E) {
21412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
21512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  unsigned argIndex = 0;
21612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
21712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // Keep looking for a format specifier until we have exhausted the string.
21812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  while (I != E) {
21912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex);
22012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // Did a fail-stop error of any kind occur when parsing the specifier?
22112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // If so, don't do any more processing.
22212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (FSR.shouldStop())
22312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return true;;
22412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // Did we exhaust the string or encounter an error that
22512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // we can recover from?
22612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (!FSR.hasValue())
22712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      continue;
22812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // We have a format specifier.  Pass it to the callback.
22912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
23012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala                                 I - FSR.getStart()))
23112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return true;
23212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
23312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  assert(I == E && "Format string not exhausted");
23412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  return false;
23512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala}
23612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
23712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//===----------------------------------------------------------------------===//
23812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala// Methods on ConversionSpecifier.
23912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//===----------------------------------------------------------------------===//
24012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialaconst char *ConversionSpecifier::toString() const {
24112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  switch (kind) {
24212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case dArg: return "d";
24312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case iArg: return "i";
24412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case oArg: return "o";
24512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case uArg: return "u";
24612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case xArg: return "x";
24712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case XArg: return "X";
24812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case fArg: return "f";
24912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case FArg: return "F";
25012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case eArg: return "e";
25112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case EArg: return "E";
25212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case gArg: return "g";
25312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case GArg: return "G";
25412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case aArg: return "a";
25512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case AArg: return "A";
25612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case cArg: return "c";
25712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case sArg: return "s";
25812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case pArg: return "p";
25912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case nArg: return "n";
26012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case PercentArg:  return "%";
26112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case ScanListArg: return "[";
26212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case InvalidSpecifier: return NULL;
26312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
26412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // MacOS X unicode extensions.
26512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case CArg: return "C";
26612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case SArg: return "S";
26712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
26812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // Objective-C specific specifiers.
26912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case ObjCObjArg: return "@";
27012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
27112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // GlibC specific specifiers.
27212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  case PrintErrno: return "m";
27312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
27412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  return NULL;
27512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala}
27612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
27712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//===----------------------------------------------------------------------===//
27812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala// Methods on PrintfSpecifier.
27912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala//===----------------------------------------------------------------------===//
28012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
28112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd FialaArgTypeResult PrintfSpecifier::getArgType(ASTContext &Ctx) const {
28212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  const PrintfConversionSpecifier &CS = getConversionSpecifier();
28312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
28412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (!CS.consumesDataArgument())
28512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return ArgTypeResult::Invalid();
28612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
28712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (CS.getKind() == ConversionSpecifier::cArg)
28812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    switch (LM.getKind()) {
28912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::None: return Ctx.IntTy;
29012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsLong: return ArgTypeResult::WIntTy;
29112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      default:
29212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        return ArgTypeResult::Invalid();
29312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    }
29412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
29512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (CS.isIntArg())
29612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    switch (LM.getKind()) {
29712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsLongDouble:
29812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        return ArgTypeResult::Invalid();
29912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::None: return Ctx.IntTy;
30012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsChar: return ArgTypeResult::AnyCharTy;
30112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsShort: return Ctx.ShortTy;
30212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsLong: return Ctx.LongTy;
30312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsLongLong: return Ctx.LongLongTy;
30412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsIntMax:
30512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        // FIXME: Return unknown for now.
30612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        return ArgTypeResult();
30712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsSizeT: return Ctx.getSizeType();
30812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsPtrDiff: return Ctx.getPointerDiffType();
30912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    }
31012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
31112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (CS.isUIntArg())
31212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    switch (LM.getKind()) {
31312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsLongDouble:
31412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        return ArgTypeResult::Invalid();
31512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::None: return Ctx.UnsignedIntTy;
31612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
31712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
31812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
31912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy;
32012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsIntMax:
32112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        // FIXME: Return unknown for now.
32212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        return ArgTypeResult();
32312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsSizeT:
32412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        // FIXME: How to get the corresponding unsigned
32512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        // version of size_t?
32612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        return ArgTypeResult();
32712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      case LengthModifier::AsPtrDiff:
32812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        // FIXME: How to get the corresponding unsigned
32912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        // version of ptrdiff_t?
33012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala        return ArgTypeResult();
33112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    }
33212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
33312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (CS.isDoubleArg()) {
33412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (LM.getKind() == LengthModifier::AsLongDouble)
33512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return Ctx.LongDoubleTy;
33612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return Ctx.DoubleTy;
33712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
33812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
33912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  switch (CS.getKind()) {
34012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case ConversionSpecifier::sArg:
34112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ?
34212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala          ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy);
34312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case ConversionSpecifier::SArg:
34412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      // FIXME: This appears to be Mac OS X specific.
34512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return ArgTypeResult::WCStrTy;
34612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case ConversionSpecifier::CArg:
34712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return Ctx.WCharTy;
34812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    case ConversionSpecifier::pArg:
34912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      return ArgTypeResult::CPointerTy;
35012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    default:
35112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      break;
35212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  }
35312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
35412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // FIXME: Handle other cases.
35512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  return ArgTypeResult();
35612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala}
35712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
35812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fialabool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt) {
35912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  // Handle strings first (char *, wchar_t *)
36012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala  if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
36112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    CS.setKind(ConversionSpecifier::sArg);
36212e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
36312e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // Disable irrelevant flags
36412e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    HasAlternativeForm = 0;
36512e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    HasLeadingZeroes = 0;
36612e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
36712e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    // Set the long length modifier for wide characters
36812e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    if (QT->getPointeeType()->isWideCharType())
36912e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala      LM.setKind(LengthModifier::AsWideChar);
37012e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala
37112e21689bc88a77c7b5b9b220fec31e049e5ec0fTodd Fiala    return true;
372  }
373
374  // We can only work with builtin types.
375  const BuiltinType *BT = QT->getAs<BuiltinType>();
376  if (!BT)
377    return false;
378
379  // Set length modifier
380  switch (BT->getKind()) {
381  case BuiltinType::Bool:
382  case BuiltinType::WChar_U:
383  case BuiltinType::WChar_S:
384  case BuiltinType::Char16:
385  case BuiltinType::Char32:
386  case BuiltinType::UInt128:
387  case BuiltinType::Int128:
388  case BuiltinType::Half:
389    // Various types which are non-trivial to correct.
390    return false;
391
392#define SIGNED_TYPE(Id, SingletonId)
393#define UNSIGNED_TYPE(Id, SingletonId)
394#define FLOATING_TYPE(Id, SingletonId)
395#define BUILTIN_TYPE(Id, SingletonId) \
396  case BuiltinType::Id:
397#include "clang/AST/BuiltinTypes.def"
398    // Misc other stuff which doesn't make sense here.
399    return false;
400
401  case BuiltinType::UInt:
402  case BuiltinType::Int:
403  case BuiltinType::Float:
404  case BuiltinType::Double:
405    LM.setKind(LengthModifier::None);
406    break;
407
408  case BuiltinType::Char_U:
409  case BuiltinType::UChar:
410  case BuiltinType::Char_S:
411  case BuiltinType::SChar:
412    LM.setKind(LengthModifier::AsChar);
413    break;
414
415  case BuiltinType::Short:
416  case BuiltinType::UShort:
417    LM.setKind(LengthModifier::AsShort);
418    break;
419
420  case BuiltinType::Long:
421  case BuiltinType::ULong:
422    LM.setKind(LengthModifier::AsLong);
423    break;
424
425  case BuiltinType::LongLong:
426  case BuiltinType::ULongLong:
427    LM.setKind(LengthModifier::AsLongLong);
428    break;
429
430  case BuiltinType::LongDouble:
431    LM.setKind(LengthModifier::AsLongDouble);
432    break;
433  }
434
435  // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
436  if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) {
437    const IdentifierInfo *Identifier = QT.getBaseTypeIdentifier();
438    if (Identifier->getName() == "size_t") {
439      LM.setKind(LengthModifier::AsSizeT);
440    } else if (Identifier->getName() == "ssize_t") {
441      // Not C99, but common in Unix.
442      LM.setKind(LengthModifier::AsSizeT);
443    } else if (Identifier->getName() == "intmax_t") {
444      LM.setKind(LengthModifier::AsIntMax);
445    } else if (Identifier->getName() == "uintmax_t") {
446      LM.setKind(LengthModifier::AsIntMax);
447    } else if (Identifier->getName() == "ptrdiff_t") {
448      LM.setKind(LengthModifier::AsPtrDiff);
449    }
450  }
451
452  // Set conversion specifier and disable any flags which do not apply to it.
453  // Let typedefs to char fall through to int, as %c is silly for uint8_t.
454  if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) {
455    CS.setKind(ConversionSpecifier::cArg);
456    LM.setKind(LengthModifier::None);
457    Precision.setHowSpecified(OptionalAmount::NotSpecified);
458    HasAlternativeForm = 0;
459    HasLeadingZeroes = 0;
460    HasPlusPrefix = 0;
461  }
462  // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
463  else if (QT->isRealFloatingType()) {
464    CS.setKind(ConversionSpecifier::fArg);
465  }
466  else if (QT->isSignedIntegerType()) {
467    CS.setKind(ConversionSpecifier::dArg);
468    HasAlternativeForm = 0;
469  }
470  else if (QT->isUnsignedIntegerType()) {
471    // Preserve the original formatting, e.g. 'X', 'o'.
472    if (!cast<PrintfConversionSpecifier>(CS).isUIntArg())
473      CS.setKind(ConversionSpecifier::uArg);
474    HasAlternativeForm = 0;
475    HasPlusPrefix = 0;
476  } else {
477    llvm_unreachable("Unexpected type");
478  }
479
480  return true;
481}
482
483void PrintfSpecifier::toString(raw_ostream &os) const {
484  // Whilst some features have no defined order, we are using the order
485  // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
486  os << "%";
487
488  // Positional args
489  if (usesPositionalArg()) {
490    os << getPositionalArgIndex() << "$";
491  }
492
493  // Conversion flags
494  if (IsLeftJustified)    os << "-";
495  if (HasPlusPrefix)      os << "+";
496  if (HasSpacePrefix)     os << " ";
497  if (HasAlternativeForm) os << "#";
498  if (HasLeadingZeroes)   os << "0";
499
500  // Minimum field width
501  FieldWidth.toString(os);
502  // Precision
503  Precision.toString(os);
504  // Length modifier
505  os << LM.toString();
506  // Conversion specifier
507  os << CS.toString();
508}
509
510bool PrintfSpecifier::hasValidPlusPrefix() const {
511  if (!HasPlusPrefix)
512    return true;
513
514  // The plus prefix only makes sense for signed conversions
515  switch (CS.getKind()) {
516  case ConversionSpecifier::dArg:
517  case ConversionSpecifier::iArg:
518  case ConversionSpecifier::fArg:
519  case ConversionSpecifier::FArg:
520  case ConversionSpecifier::eArg:
521  case ConversionSpecifier::EArg:
522  case ConversionSpecifier::gArg:
523  case ConversionSpecifier::GArg:
524  case ConversionSpecifier::aArg:
525  case ConversionSpecifier::AArg:
526    return true;
527
528  default:
529    return false;
530  }
531}
532
533bool PrintfSpecifier::hasValidAlternativeForm() const {
534  if (!HasAlternativeForm)
535    return true;
536
537  // Alternate form flag only valid with the oxXaAeEfFgG conversions
538  switch (CS.getKind()) {
539  case ConversionSpecifier::oArg:
540  case ConversionSpecifier::xArg:
541  case ConversionSpecifier::XArg:
542  case ConversionSpecifier::aArg:
543  case ConversionSpecifier::AArg:
544  case ConversionSpecifier::eArg:
545  case ConversionSpecifier::EArg:
546  case ConversionSpecifier::fArg:
547  case ConversionSpecifier::FArg:
548  case ConversionSpecifier::gArg:
549  case ConversionSpecifier::GArg:
550    return true;
551
552  default:
553    return false;
554  }
555}
556
557bool PrintfSpecifier::hasValidLeadingZeros() const {
558  if (!HasLeadingZeroes)
559    return true;
560
561  // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
562  switch (CS.getKind()) {
563  case ConversionSpecifier::dArg:
564  case ConversionSpecifier::iArg:
565  case ConversionSpecifier::oArg:
566  case ConversionSpecifier::uArg:
567  case ConversionSpecifier::xArg:
568  case ConversionSpecifier::XArg:
569  case ConversionSpecifier::aArg:
570  case ConversionSpecifier::AArg:
571  case ConversionSpecifier::eArg:
572  case ConversionSpecifier::EArg:
573  case ConversionSpecifier::fArg:
574  case ConversionSpecifier::FArg:
575  case ConversionSpecifier::gArg:
576  case ConversionSpecifier::GArg:
577    return true;
578
579  default:
580    return false;
581  }
582}
583
584bool PrintfSpecifier::hasValidSpacePrefix() const {
585  if (!HasSpacePrefix)
586    return true;
587
588  // The space prefix only makes sense for signed conversions
589  switch (CS.getKind()) {
590  case ConversionSpecifier::dArg:
591  case ConversionSpecifier::iArg:
592  case ConversionSpecifier::fArg:
593  case ConversionSpecifier::FArg:
594  case ConversionSpecifier::eArg:
595  case ConversionSpecifier::EArg:
596  case ConversionSpecifier::gArg:
597  case ConversionSpecifier::GArg:
598  case ConversionSpecifier::aArg:
599  case ConversionSpecifier::AArg:
600    return true;
601
602  default:
603    return false;
604  }
605}
606
607bool PrintfSpecifier::hasValidLeftJustified() const {
608  if (!IsLeftJustified)
609    return true;
610
611  // The left justified flag is valid for all conversions except n
612  switch (CS.getKind()) {
613  case ConversionSpecifier::nArg:
614    return false;
615
616  default:
617    return true;
618  }
619}
620
621bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
622  if (!HasThousandsGrouping)
623    return true;
624
625  switch (CS.getKind()) {
626    case ConversionSpecifier::dArg:
627    case ConversionSpecifier::iArg:
628    case ConversionSpecifier::uArg:
629    case ConversionSpecifier::fArg:
630    case ConversionSpecifier::FArg:
631    case ConversionSpecifier::gArg:
632    case ConversionSpecifier::GArg:
633      return true;
634    default:
635      return false;
636  }
637}
638
639bool PrintfSpecifier::hasValidPrecision() const {
640  if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
641    return true;
642
643  // Precision is only valid with the diouxXaAeEfFgGs conversions
644  switch (CS.getKind()) {
645  case ConversionSpecifier::dArg:
646  case ConversionSpecifier::iArg:
647  case ConversionSpecifier::oArg:
648  case ConversionSpecifier::uArg:
649  case ConversionSpecifier::xArg:
650  case ConversionSpecifier::XArg:
651  case ConversionSpecifier::aArg:
652  case ConversionSpecifier::AArg:
653  case ConversionSpecifier::eArg:
654  case ConversionSpecifier::EArg:
655  case ConversionSpecifier::fArg:
656  case ConversionSpecifier::FArg:
657  case ConversionSpecifier::gArg:
658  case ConversionSpecifier::GArg:
659  case ConversionSpecifier::sArg:
660    return true;
661
662  default:
663    return false;
664  }
665}
666bool PrintfSpecifier::hasValidFieldWidth() const {
667  if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
668      return true;
669
670  // The field width is valid for all conversions except n
671  switch (CS.getKind()) {
672  case ConversionSpecifier::nArg:
673    return false;
674
675  default:
676    return true;
677  }
678}
679