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