PrintfFormatString.cpp revision 1ad23d62007162df82b58bca31b4aa277a5f6586
18c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==// 28c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// 38c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// The LLVM Compiler Infrastructure 48c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// 58c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// This file is distributed under the University of Illinois Open Source 68c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// License. See LICENSE.TXT for details. 78c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// 88c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//===----------------------------------------------------------------------===// 98c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// 108c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// Handling of format string in printf and friends. The structure of format 118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// strings for fprintf() are described in C99 7.19.6.1. 128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// 138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//===----------------------------------------------------------------------===// 148c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 15305c613af6cfc40e519c75d9d2c84c6fa9a841c0Ted Kremenek#include "clang/Analysis/Analyses/FormatString.h" 168c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie#include "FormatStringParsing.h" 178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 188c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing clang::analyze_format_string::ArgType; 198c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing clang::analyze_format_string::FormatStringHandler; 208c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing clang::analyze_format_string::LengthModifier; 218c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing clang::analyze_format_string::OptionalAmount; 228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing clang::analyze_format_string::ConversionSpecifier; 238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing clang::analyze_printf::PrintfSpecifier; 248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing namespace clang; 268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikietypedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier> 288c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie PrintfSpecifierResult; 298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//===----------------------------------------------------------------------===// 318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// Methods for parsing format strings. 328c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//===----------------------------------------------------------------------===// 338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikieusing analyze_format_string::ParseNonPositionAmount; 358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 3649fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenkostatic bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS, 3749fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko const char *Start, const char *&Beg, const char *E, 3849fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko unsigned *argIndex) { 3949fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko if (argIndex) { 4049fdccb4595862828aa5cadc1497d466a8031ddaDmitri Gribenko FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex)); 418c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } else { 428c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 438c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie analyze_format_string::PrecisionPos); 448c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (Amt.isInvalid()) 458c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie FS.setPrecision(Amt); 478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 488c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return false; 498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie} 508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikiestatic PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H, 528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const char *&Beg, 538c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const char *E, 548c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie unsigned &argIndex, 558c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const LangOptions &LO) { 568c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie using namespace clang::analyze_format_string; 588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie using namespace clang::analyze_printf; 598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 60da313592441db36cf4b06be97c4bcc238ee6fa9cArgyrios Kyrtzidis const char *I = Beg; 618c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const char *Start = 0; 628c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie UpdateOnReturn <const char*> UpdateBeg(Beg, I); 638c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 648c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Look for a '%' character that indicates the start of a format specifier. 658c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie for ( ; I != E ; ++I) { 668c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie char c = *I; 678c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (c == '\0') { 688c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Detect spurious null characters, which are likely errors. 698c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie H.HandleNullChar(I); 708c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 718c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 728c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (c == '%') { 738c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie Start = I++; // Record the start of the format specifier. 748c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie break; 758c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 768c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 778c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 788c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // No format specifier found? 798c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (!Start) 808c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return false; 818c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 828c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (I == E) { 838c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // No more characters left? 848c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie H.HandleIncompleteSpecifier(Start, E - Start); 858c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 868c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 878c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 888c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie PrintfSpecifier FS; 898c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (ParseArgPosition(H, FS, Start, I, E)) 908c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 918c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 928c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (I == E) { 938c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // No more characters left? 948c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie H.HandleIncompleteSpecifier(Start, E - Start); 958c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 968c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 978c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 988c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Look for flags (if any). 998c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie bool hasMore = true; 1008c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie for ( ; I != E; ++I) { 1018c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie switch (*I) { 1028c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie default: hasMore = false; break; 1038c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case '\'': 1048c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // FIXME: POSIX specific. Always accept? 1058c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie FS.setHasThousandsGrouping(I); 1068c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie break; 1078c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case '-': FS.setIsLeftJustified(I); break; 1088c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case '+': FS.setHasPlusPrefix(I); break; 1098c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case ' ': FS.setHasSpacePrefix(I); break; 1108c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case '#': FS.setHasAlternativeForm(I); break; 1118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case '0': FS.setHasLeadingZeros(I); break; 1128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 1138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (!hasMore) 1148c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie break; 1158c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 1168c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 1178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (I == E) { 1188c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // No more characters left? 1198c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie H.HandleIncompleteSpecifier(Start, E - Start); 1208c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 1218c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 1228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 1238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Look for the field width (if any). 1248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (ParseFieldWidth(H, FS, Start, I, E, 1258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie FS.usesPositionalArg() ? 0 : &argIndex)) 1268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 1278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 1288c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (I == E) { 1298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // No more characters left? 1308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie H.HandleIncompleteSpecifier(Start, E - Start); 1318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 1328c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 1338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 1348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Look for the precision (if any). 1358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (*I == '.') { 1368c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie ++I; 1378c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (I == E) { 1388c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie H.HandleIncompleteSpecifier(Start, E - Start); 1398c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 1408c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 1418c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 1428c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (ParsePrecision(H, FS, Start, I, E, 1438c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie FS.usesPositionalArg() ? 0 : &argIndex)) 1448c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 1458c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 1468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (I == E) { 1478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // No more characters left? 1488c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie H.HandleIncompleteSpecifier(Start, E - Start); 1498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 1508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 1518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 1528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 1538c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Look for the length modifier. 1548c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (ParseLengthModifier(FS, I, E, LO) && I == E) { 155da313592441db36cf4b06be97c4bcc238ee6fa9cArgyrios Kyrtzidis // No more characters left? 1568c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie H.HandleIncompleteSpecifier(Start, E - Start); 1578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 1588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 1598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 1608c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (*I == '\0') { 1618c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Detect spurious null characters, which are likely errors. 1628c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie H.HandleNullChar(I); 1638c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 1648c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 1658c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 1668c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Finally, look for the conversion specifier. 1678c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const char *conversionPosition = I++; 1688c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 1698c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie switch (*conversionPosition) { 1708c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie default: 1718c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie break; 1728c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // C99: 7.19.6.1 (section 8). 1738c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case '%': k = ConversionSpecifier::PercentArg; break; 1748c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'A': k = ConversionSpecifier::AArg; break; 1758c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'E': k = ConversionSpecifier::EArg; break; 1768c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'F': k = ConversionSpecifier::FArg; break; 1778c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'G': k = ConversionSpecifier::GArg; break; 1788c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'X': k = ConversionSpecifier::XArg; break; 1798c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'a': k = ConversionSpecifier::aArg; break; 1808c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'c': k = ConversionSpecifier::cArg; break; 1818c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'd': k = ConversionSpecifier::dArg; break; 1828c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'e': k = ConversionSpecifier::eArg; break; 1838c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'f': k = ConversionSpecifier::fArg; break; 1848c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'g': k = ConversionSpecifier::gArg; break; 1858c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'i': k = ConversionSpecifier::iArg; break; 1868c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'n': k = ConversionSpecifier::nArg; break; 1878c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'o': k = ConversionSpecifier::oArg; break; 1888c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'p': k = ConversionSpecifier::pArg; break; 1898c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 's': k = ConversionSpecifier::sArg; break; 1908c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'u': k = ConversionSpecifier::uArg; break; 1918c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'x': k = ConversionSpecifier::xArg; break; 1928c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // POSIX specific. 1938c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'C': k = ConversionSpecifier::CArg; break; 1948c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'S': k = ConversionSpecifier::SArg; break; 1958c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Objective-C. 1968c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case '@': k = ConversionSpecifier::ObjCObjArg; break; 1978c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Glibc specific. 1988c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case 'm': k = ConversionSpecifier::PrintErrno; break; 1998c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 2008c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie PrintfConversionSpecifier CS(conversionPosition, k); 2018c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie FS.setConversionSpecifier(CS); 2023159819ed71a2e814175a593147f7637a423ba56Benjamin Kramer if (CS.consumesDataArgument() && !FS.usesPositionalArg()) 2033159819ed71a2e814175a593147f7637a423ba56Benjamin Kramer FS.setArgIndex(argIndex++); 2048c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 2058c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (k == ConversionSpecifier::InvalidSpecifier) { 2068c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Assume the conversion takes one argument. 2078c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start); 2088c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 2098c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return PrintfSpecifierResult(Start, FS); 2108c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie} 2118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 2128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikiebool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H, 2138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const char *I, 2148c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const char *E, 2158c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const LangOptions &LO) { 2168c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 2178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie unsigned argIndex = 0; 2188c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 2198c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Keep looking for a format specifier until we have exhausted the string. 2208c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie while (I != E) { 2218c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex, 2228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie LO); 2238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Did a fail-stop error of any kind occur when parsing the specifier? 2248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // If so, don't do any more processing. 2258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (FSR.shouldStop()) 2268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 2278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // Did we exhaust the string or encounter an error that 22860ad16b7e24cdb88c577c107b69da85458000858David Blaikie // we can recover from? 2298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (!FSR.hasValue()) 2308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie continue; 2318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // We have a format specifier. Pass it to the callback. 23260ad16b7e24cdb88c577c107b69da85458000858David Blaikie if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(), 2338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie I - FSR.getStart())) 2348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return true; 2358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 2368c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie assert(I == E && "Format string not exhausted"); 2378c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return false; 2388c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie} 2398c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 2408c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//===----------------------------------------------------------------------===// 2418c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie// Methods on PrintfSpecifier. 2428c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie//===----------------------------------------------------------------------===// 2438c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 2448c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid BlaikieArgType PrintfSpecifier::getArgType(ASTContext &Ctx, 2458c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie bool IsObjCLiteral) const { 2468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie const PrintfConversionSpecifier &CS = getConversionSpecifier(); 2478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 2488c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (!CS.consumesDataArgument()) 2498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::Invalid(); 2508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 2518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (CS.getKind() == ConversionSpecifier::cArg) 2528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie switch (LM.getKind()) { 253bae2b31822e3c2139b5f8fbb127e4c5674cce6dbDavid Blaikie case LengthModifier::None: return Ctx.IntTy; 254bae2b31822e3c2139b5f8fbb127e4c5674cce6dbDavid Blaikie case LengthModifier::AsLong: 2558c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(ArgType::WIntTy, "wint_t"); 2568c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie default: 2578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::Invalid(); 2588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 2598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 2608c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (CS.isIntArg()) 2618c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie switch (LM.getKind()) { 2628c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsLongDouble: 2638c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // GNU extension. 2648c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return Ctx.LongLongTy; 2658c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::None: return Ctx.IntTy; 2668c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsChar: return ArgType::AnyCharTy; 2678c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsShort: return Ctx.ShortTy; 2688c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsLong: return Ctx.LongTy; 2698c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsLongLong: 2708c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsQuad: 2718c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return Ctx.LongLongTy; 2728c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsIntMax: 2738c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(Ctx.getIntMaxType(), "intmax_t"); 2748c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsSizeT: 2758c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // FIXME: How to get the corresponding signed version of size_t? 2768c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(); 2778c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsPtrDiff: 2788c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"); 2798c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsAllocate: 2808c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsMAllocate: 2818c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::Invalid(); 2828c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 2838c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 2848c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (CS.isUIntArg()) 2858c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie switch (LM.getKind()) { 2868c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsLongDouble: 2878c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // GNU extension. 2888c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return Ctx.UnsignedLongLongTy; 2898c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::None: return Ctx.UnsignedIntTy; 2908c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsChar: return Ctx.UnsignedCharTy; 2918c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsShort: return Ctx.UnsignedShortTy; 2928c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsLong: return Ctx.UnsignedLongTy; 2938c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsLongLong: 2948c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsQuad: 2958c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return Ctx.UnsignedLongLongTy; 2968c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsIntMax: 2978c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(Ctx.getUIntMaxType(), "uintmax_t"); 2988c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsSizeT: 2998c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(Ctx.getSizeType(), "size_t"); 3008c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsPtrDiff: 3018c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // FIXME: How to get the corresponding unsigned 3028c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie // version of ptrdiff_t? 3038c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(); 3048c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsAllocate: 3058c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsMAllocate: 3068c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::Invalid(); 3078c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 3088c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 3098c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (CS.isDoubleArg()) { 3108c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (LM.getKind() == LengthModifier::AsLongDouble) 3118c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return Ctx.LongDoubleTy; 3128c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return Ctx.DoubleTy; 3138c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 3148c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 3158c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (CS.getKind() == ConversionSpecifier::nArg) { 3168c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie switch (LM.getKind()) { 3178c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::None: 3188c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::PtrTo(Ctx.IntTy); 3198c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsChar: 3208c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::PtrTo(Ctx.SignedCharTy); 3218c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsShort: 3228c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::PtrTo(Ctx.ShortTy); 3238c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsLong: 3248c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::PtrTo(Ctx.LongTy); 3258c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsLongLong: 3268c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsQuad: 3278c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::PtrTo(Ctx.LongLongTy); 3288c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsIntMax: 3298c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t")); 3308c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsSizeT: 3318c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(); // FIXME: ssize_t 3328c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsPtrDiff: 3338c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t")); 3348c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsLongDouble: 3358c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(); // FIXME: Is this a known extension? 3368c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsAllocate: 3378c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case LengthModifier::AsMAllocate: 33860ad16b7e24cdb88c577c107b69da85458000858David Blaikie return ArgType::Invalid(); 3398c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 3408c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 3418c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie 3428c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie switch (CS.getKind()) { 3438c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case ConversionSpecifier::sArg: 3448c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (LM.getKind() == LengthModifier::AsWideChar) { 3458c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (IsObjCLiteral) 3468c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()); 3478c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(ArgType::WCStrTy, "wchar_t *"); 3488c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie } 3498c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::CStrTy; 3508c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case ConversionSpecifier::SArg: 3518c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (IsObjCLiteral) 3528c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()); 3538c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(ArgType::WCStrTy, "wchar_t *"); 3548c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case ConversionSpecifier::CArg: 3558c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie if (IsObjCLiteral) 3568c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return Ctx.UnsignedShortTy; 3578c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType(Ctx.WCharTy, "wchar_t"); 3588c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case ConversionSpecifier::pArg: 3598c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::CPointerTy; 3608c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie case ConversionSpecifier::ObjCObjArg: 3618c0b3787e7ccc7978b42dfbb84da2b802c743a5dDavid Blaikie return ArgType::ObjCPointerTy; 362 default: 363 break; 364 } 365 366 // FIXME: Handle other cases. 367 return ArgType(); 368} 369 370bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt, 371 ASTContext &Ctx, bool IsObjCLiteral) { 372 // %n is different from other conversion specifiers; don't try to fix it. 373 if (CS.getKind() == ConversionSpecifier::nArg) 374 return false; 375 376 // Handle Objective-C objects first. Note that while the '%@' specifier will 377 // not warn for structure pointer or void pointer arguments (because that's 378 // how CoreFoundation objects are implemented), we only show a fixit for '%@' 379 // if we know it's an object (block, id, class, or __attribute__((NSObject))). 380 if (QT->isObjCRetainableType()) { 381 if (!IsObjCLiteral) 382 return false; 383 384 CS.setKind(ConversionSpecifier::ObjCObjArg); 385 386 // Disable irrelevant flags 387 HasThousandsGrouping = false; 388 HasPlusPrefix = false; 389 HasSpacePrefix = false; 390 HasAlternativeForm = false; 391 HasLeadingZeroes = false; 392 Precision.setHowSpecified(OptionalAmount::NotSpecified); 393 LM.setKind(LengthModifier::None); 394 395 return true; 396 } 397 398 // Handle strings next (char *, wchar_t *) 399 if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { 400 CS.setKind(ConversionSpecifier::sArg); 401 402 // Disable irrelevant flags 403 HasAlternativeForm = 0; 404 HasLeadingZeroes = 0; 405 406 // Set the long length modifier for wide characters 407 if (QT->getPointeeType()->isWideCharType()) 408 LM.setKind(LengthModifier::AsWideChar); 409 else 410 LM.setKind(LengthModifier::None); 411 412 return true; 413 } 414 415 // If it's an enum, get its underlying type. 416 if (const EnumType *ETy = QT->getAs<EnumType>()) 417 QT = ETy->getDecl()->getIntegerType(); 418 419 // We can only work with builtin types. 420 const BuiltinType *BT = QT->getAs<BuiltinType>(); 421 if (!BT) 422 return false; 423 424 // Set length modifier 425 switch (BT->getKind()) { 426 case BuiltinType::Bool: 427 case BuiltinType::WChar_U: 428 case BuiltinType::WChar_S: 429 case BuiltinType::Char16: 430 case BuiltinType::Char32: 431 case BuiltinType::UInt128: 432 case BuiltinType::Int128: 433 case BuiltinType::Half: 434 // Various types which are non-trivial to correct. 435 return false; 436 437#define SIGNED_TYPE(Id, SingletonId) 438#define UNSIGNED_TYPE(Id, SingletonId) 439#define FLOATING_TYPE(Id, SingletonId) 440#define BUILTIN_TYPE(Id, SingletonId) \ 441 case BuiltinType::Id: 442#include "clang/AST/BuiltinTypes.def" 443 // Misc other stuff which doesn't make sense here. 444 return false; 445 446 case BuiltinType::UInt: 447 case BuiltinType::Int: 448 case BuiltinType::Float: 449 case BuiltinType::Double: 450 LM.setKind(LengthModifier::None); 451 break; 452 453 case BuiltinType::Char_U: 454 case BuiltinType::UChar: 455 case BuiltinType::Char_S: 456 case BuiltinType::SChar: 457 LM.setKind(LengthModifier::AsChar); 458 break; 459 460 case BuiltinType::Short: 461 case BuiltinType::UShort: 462 LM.setKind(LengthModifier::AsShort); 463 break; 464 465 case BuiltinType::Long: 466 case BuiltinType::ULong: 467 LM.setKind(LengthModifier::AsLong); 468 break; 469 470 case BuiltinType::LongLong: 471 case BuiltinType::ULongLong: 472 LM.setKind(LengthModifier::AsLongLong); 473 break; 474 475 case BuiltinType::LongDouble: 476 LM.setKind(LengthModifier::AsLongDouble); 477 break; 478 } 479 480 // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99. 481 if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus0x)) 482 namedTypeToLengthModifier(QT, LM); 483 484 // If fixing the length modifier was enough, we are done. 485 if (hasValidLengthModifier(Ctx.getTargetInfo())) { 486 const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral); 487 if (ATR.isValid() && ATR.matchesType(Ctx, QT)) 488 return true; 489 } 490 491 // Set conversion specifier and disable any flags which do not apply to it. 492 // Let typedefs to char fall through to int, as %c is silly for uint8_t. 493 if (isa<TypedefType>(QT) && QT->isAnyCharacterType()) { 494 CS.setKind(ConversionSpecifier::cArg); 495 LM.setKind(LengthModifier::None); 496 Precision.setHowSpecified(OptionalAmount::NotSpecified); 497 HasAlternativeForm = 0; 498 HasLeadingZeroes = 0; 499 HasPlusPrefix = 0; 500 } 501 // Test for Floating type first as LongDouble can pass isUnsignedIntegerType 502 else if (QT->isRealFloatingType()) { 503 CS.setKind(ConversionSpecifier::fArg); 504 } 505 else if (QT->isSignedIntegerType()) { 506 CS.setKind(ConversionSpecifier::dArg); 507 HasAlternativeForm = 0; 508 } 509 else if (QT->isUnsignedIntegerType()) { 510 CS.setKind(ConversionSpecifier::uArg); 511 HasAlternativeForm = 0; 512 HasPlusPrefix = 0; 513 } else { 514 llvm_unreachable("Unexpected type"); 515 } 516 517 return true; 518} 519 520void PrintfSpecifier::toString(raw_ostream &os) const { 521 // Whilst some features have no defined order, we are using the order 522 // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1) 523 os << "%"; 524 525 // Positional args 526 if (usesPositionalArg()) { 527 os << getPositionalArgIndex() << "$"; 528 } 529 530 // Conversion flags 531 if (IsLeftJustified) os << "-"; 532 if (HasPlusPrefix) os << "+"; 533 if (HasSpacePrefix) os << " "; 534 if (HasAlternativeForm) os << "#"; 535 if (HasLeadingZeroes) os << "0"; 536 537 // Minimum field width 538 FieldWidth.toString(os); 539 // Precision 540 Precision.toString(os); 541 // Length modifier 542 os << LM.toString(); 543 // Conversion specifier 544 os << CS.toString(); 545} 546 547bool PrintfSpecifier::hasValidPlusPrefix() const { 548 if (!HasPlusPrefix) 549 return true; 550 551 // The plus prefix only makes sense for signed conversions 552 switch (CS.getKind()) { 553 case ConversionSpecifier::dArg: 554 case ConversionSpecifier::iArg: 555 case ConversionSpecifier::fArg: 556 case ConversionSpecifier::FArg: 557 case ConversionSpecifier::eArg: 558 case ConversionSpecifier::EArg: 559 case ConversionSpecifier::gArg: 560 case ConversionSpecifier::GArg: 561 case ConversionSpecifier::aArg: 562 case ConversionSpecifier::AArg: 563 return true; 564 565 default: 566 return false; 567 } 568} 569 570bool PrintfSpecifier::hasValidAlternativeForm() const { 571 if (!HasAlternativeForm) 572 return true; 573 574 // Alternate form flag only valid with the oxXaAeEfFgG conversions 575 switch (CS.getKind()) { 576 case ConversionSpecifier::oArg: 577 case ConversionSpecifier::xArg: 578 case ConversionSpecifier::XArg: 579 case ConversionSpecifier::aArg: 580 case ConversionSpecifier::AArg: 581 case ConversionSpecifier::eArg: 582 case ConversionSpecifier::EArg: 583 case ConversionSpecifier::fArg: 584 case ConversionSpecifier::FArg: 585 case ConversionSpecifier::gArg: 586 case ConversionSpecifier::GArg: 587 return true; 588 589 default: 590 return false; 591 } 592} 593 594bool PrintfSpecifier::hasValidLeadingZeros() const { 595 if (!HasLeadingZeroes) 596 return true; 597 598 // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions 599 switch (CS.getKind()) { 600 case ConversionSpecifier::dArg: 601 case ConversionSpecifier::iArg: 602 case ConversionSpecifier::oArg: 603 case ConversionSpecifier::uArg: 604 case ConversionSpecifier::xArg: 605 case ConversionSpecifier::XArg: 606 case ConversionSpecifier::aArg: 607 case ConversionSpecifier::AArg: 608 case ConversionSpecifier::eArg: 609 case ConversionSpecifier::EArg: 610 case ConversionSpecifier::fArg: 611 case ConversionSpecifier::FArg: 612 case ConversionSpecifier::gArg: 613 case ConversionSpecifier::GArg: 614 return true; 615 616 default: 617 return false; 618 } 619} 620 621bool PrintfSpecifier::hasValidSpacePrefix() const { 622 if (!HasSpacePrefix) 623 return true; 624 625 // The space prefix only makes sense for signed conversions 626 switch (CS.getKind()) { 627 case ConversionSpecifier::dArg: 628 case ConversionSpecifier::iArg: 629 case ConversionSpecifier::fArg: 630 case ConversionSpecifier::FArg: 631 case ConversionSpecifier::eArg: 632 case ConversionSpecifier::EArg: 633 case ConversionSpecifier::gArg: 634 case ConversionSpecifier::GArg: 635 case ConversionSpecifier::aArg: 636 case ConversionSpecifier::AArg: 637 return true; 638 639 default: 640 return false; 641 } 642} 643 644bool PrintfSpecifier::hasValidLeftJustified() const { 645 if (!IsLeftJustified) 646 return true; 647 648 // The left justified flag is valid for all conversions except n 649 switch (CS.getKind()) { 650 case ConversionSpecifier::nArg: 651 return false; 652 653 default: 654 return true; 655 } 656} 657 658bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const { 659 if (!HasThousandsGrouping) 660 return true; 661 662 switch (CS.getKind()) { 663 case ConversionSpecifier::dArg: 664 case ConversionSpecifier::iArg: 665 case ConversionSpecifier::uArg: 666 case ConversionSpecifier::fArg: 667 case ConversionSpecifier::FArg: 668 case ConversionSpecifier::gArg: 669 case ConversionSpecifier::GArg: 670 return true; 671 default: 672 return false; 673 } 674} 675 676bool PrintfSpecifier::hasValidPrecision() const { 677 if (Precision.getHowSpecified() == OptionalAmount::NotSpecified) 678 return true; 679 680 // Precision is only valid with the diouxXaAeEfFgGs conversions 681 switch (CS.getKind()) { 682 case ConversionSpecifier::dArg: 683 case ConversionSpecifier::iArg: 684 case ConversionSpecifier::oArg: 685 case ConversionSpecifier::uArg: 686 case ConversionSpecifier::xArg: 687 case ConversionSpecifier::XArg: 688 case ConversionSpecifier::aArg: 689 case ConversionSpecifier::AArg: 690 case ConversionSpecifier::eArg: 691 case ConversionSpecifier::EArg: 692 case ConversionSpecifier::fArg: 693 case ConversionSpecifier::FArg: 694 case ConversionSpecifier::gArg: 695 case ConversionSpecifier::GArg: 696 case ConversionSpecifier::sArg: 697 return true; 698 699 default: 700 return false; 701 } 702} 703bool PrintfSpecifier::hasValidFieldWidth() const { 704 if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified) 705 return true; 706 707 // The field width is valid for all conversions except n 708 switch (CS.getKind()) { 709 case ConversionSpecifier::nArg: 710 return false; 711 712 default: 713 return true; 714 } 715} 716