PrintfFormatString.cpp revision 87260c7eabf88eb2009ba2ba20150cd897483241
18f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//= PrintfFormatStrings.cpp - Analysis of printf format strings --*- C++ -*-==// 28f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// 38f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// The LLVM Compiler Infrastructure 48f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// 58f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// This file is distributed under the University of Illinois Open Source 68f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// License. See LICENSE.TXT for details. 78f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// 88f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//===----------------------------------------------------------------------===// 98f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// 108f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// Handling of format string in printf and friends. The structure of format 118f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// strings for fprintf() are described in C99 7.19.6.1. 128f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek// 138f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek//===----------------------------------------------------------------------===// 148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 158f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek#include "clang/Analysis/Analyses/PrintfFormatString.h" 1633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek#include "clang/AST/ASTContext.h" 178f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 184b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenekusing clang::analyze_printf::FormatSpecifier; 194b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenekusing clang::analyze_printf::OptionalAmount; 2033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenekusing clang::analyze_printf::ArgTypeResult; 2174d56a168966ff015824279a24aaf566180ed97dTed Kremenekusing clang::analyze_printf::FormatStringHandler; 22808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenekusing namespace clang; 238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 248f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremeneknamespace { 258f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekclass FormatSpecifierResult { 268f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FormatSpecifier FS; 278f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *Start; 2826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek bool Stop; 298f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekpublic: 3026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek FormatSpecifierResult(bool stop = false) 3126ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek : Start(0), Stop(stop) {} 328f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FormatSpecifierResult(const char *start, 33d2dcece5882215e92a80bff8a7b7fd2fd81d7086Ted Kremenek const FormatSpecifier &fs) 3426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek : FS(fs), Start(start), Stop(false) {} 358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 378f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *getStart() const { return Start; } 3826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek bool shouldStop() const { return Stop; } 398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek bool hasValue() const { return Start != 0; } 408f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const FormatSpecifier &getValue() const { 418f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek assert(hasValue()); 428f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return FS; 438f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 44d2dcece5882215e92a80bff8a7b7fd2fd81d7086Ted Kremenek const FormatSpecifier &getValue() { return FS; } 458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}; 468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} // end anonymous namespace 478f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 488f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenektemplate <typename T> 498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekclass UpdateOnReturn { 508f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek T &ValueToUpdate; 518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const T &ValueToCopy; 528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekpublic: 538f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek UpdateOnReturn(T &valueToUpdate, const T &valueToCopy) 548f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {} 554e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 568f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ~UpdateOnReturn() { 578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ValueToUpdate = ValueToCopy; 588f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 594e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek}; 604e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 614e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 624e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods for parsing format strings. 634e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 648f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 658f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekstatic OptionalAmount ParseAmount(const char *&Beg, const char *E) { 668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *I = Beg; 678f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek UpdateOnReturn <const char*> UpdateBeg(Beg, I); 684e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek bool foundDigits = false; 708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek unsigned accumulator = 0; 718f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 728f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek for ( ; I != E; ++I) { 738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek char c = *I; 748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (c >= '0' && c <= '9') { 758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek foundDigits = true; 768f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek accumulator += (accumulator * 10) + (c - '0'); 778f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek continue; 788f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 798f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 808f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (foundDigits) 810d27735c51f5bd392e673cf39a675e14e9442387Ted Kremenek return OptionalAmount(accumulator, Beg); 824e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 830d27735c51f5bd392e673cf39a675e14e9442387Ted Kremenek if (c == '*') { 840d27735c51f5bd392e673cf39a675e14e9442387Ted Kremenek ++I; 850d27735c51f5bd392e673cf39a675e14e9442387Ted Kremenek return OptionalAmount(OptionalAmount::Arg, Beg); 860d27735c51f5bd392e673cf39a675e14e9442387Ted Kremenek } 874e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 888f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 898f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 904e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 914e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return OptionalAmount(); 928f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} 938f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 94808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenekstatic FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H, 9574d56a168966ff015824279a24aaf566180ed97dTed Kremenek const char *&Beg, 9674d56a168966ff015824279a24aaf566180ed97dTed Kremenek const char *E) { 974e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 984b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenek using namespace clang::analyze_printf; 994e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 1008f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *I = Beg; 101c7ae51a3cd9460db8280e8623c90614f246e46d2Ted Kremenek const char *Start = 0; 1028f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek UpdateOnReturn <const char*> UpdateBeg(Beg, I); 1038f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 1048f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for a '%' character that indicates the start of a format specifier. 105e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek for ( ; I != E ; ++I) { 1068f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek char c = *I; 1078f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (c == '\0') { 1088f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Detect spurious null characters, which are likely errors. 1098f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek H.HandleNullChar(I); 1108f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 1118f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 1128f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (c == '%') { 113e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek Start = I++; // Record the start of the format specifier. 1148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 1158f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 1168f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 1174e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 1188f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No format specifier found? 1198f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (!Start) 1208f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return false; 1214e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 1228f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 1238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 124808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 1258f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 1268f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 1274e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 1288f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FormatSpecifier FS; 1294e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 1308f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for flags (if any). 1318f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek bool hasMore = true; 1328f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek for ( ; I != E; ++I) { 1338f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek switch (*I) { 1348f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek default: hasMore = false; break; 1358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '-': FS.setIsLeftJustified(); break; 1368f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '+': FS.setHasPlusPrefix(); break; 1378f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case ' ': FS.setHasSpacePrefix(); break; 1388f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '#': FS.setHasAlternativeForm(); break; 1398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '0': FS.setHasLeadingZeros(); break; 1408f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 1418f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (!hasMore) 1428f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 1434e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 1448f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 1458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 1468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 147808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 1488f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 1498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 1504e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 1518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for the field width (if any). 1528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FS.setFieldWidth(ParseAmount(I, E)); 1534e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 1548f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 1558f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 156808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 1578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 1584e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 1594e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 1604e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek // Look for the precision (if any). 1618f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (*I == '.') { 162808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek ++I; 1638f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 164808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 1658f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 1668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 1674e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 1688f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FS.setPrecision(ParseAmount(I, E)); 1698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 1708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 1718f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 172808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 1738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 1748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 1758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 1768f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 1778f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for the length modifier. 1788f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek LengthModifier lm = None; 1798f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek switch (*I) { 1808f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek default: 1818f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 1828f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case 'h': 1838f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ++I; 1844e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek lm = (I != E && *I == 'h') ? ++I, AsChar : AsShort; 1858f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 1868f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case 'l': 1878f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ++I; 1888f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek lm = (I != E && *I == 'l') ? ++I, AsLongLong : AsLong; 1898f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 1908f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case 'j': lm = AsIntMax; ++I; break; 1918f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case 'z': lm = AsSizeT; ++I; break; 1928f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case 't': lm = AsPtrDiff; ++I; break; 1938f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case 'L': lm = AsLongDouble; ++I; break; 19401aefc6d20fbfd50bfb83926226dee86dd31c9c5Daniel Dunbar case 'q': lm = AsLongLong; ++I; break; 1958f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 1968f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FS.setLengthModifier(lm); 1974e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 1988f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 1998f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 200808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 2018f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2028f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 203df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek 2044dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek if (*I == '\0') { 205df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek // Detect spurious null characters, which are likely errors. 206df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek H.HandleNullChar(I); 207df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek return true; 2084dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek } 2094e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2108f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Finally, look for the conversion specifier. 211a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek const char *conversionPosition = I++; 21226ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 213a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek switch (*conversionPosition) { 2148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek default: 21526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek break; 216c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek // C99: 7.19.6.1 (section 8). 21787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case '%': k = ConversionSpecifier::PercentArg; break; 21887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'A': k = ConversionSpecifier::AArg; break; 219a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'E': k = ConversionSpecifier::EArg; break; 22087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'F': k = ConversionSpecifier::FArg; break; 221a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'G': k = ConversionSpecifier::GArg; break; 22287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'X': k = ConversionSpecifier::XArg; break; 223a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'a': k = ConversionSpecifier::aArg; break; 224a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'c': k = ConversionSpecifier::IntAsCharArg; break; 22587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'd': k = ConversionSpecifier::dArg; break; 22687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'e': k = ConversionSpecifier::eArg; break; 22787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'f': k = ConversionSpecifier::fArg; break; 22887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'g': k = ConversionSpecifier::gArg; break; 22987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'i': k = ConversionSpecifier::iArg; break; 230a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'n': k = ConversionSpecifier::OutIntPtrArg; break; 23187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'o': k = ConversionSpecifier::oArg; break; 23287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'p': k = ConversionSpecifier::VoidPtrArg; break; 23387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 's': k = ConversionSpecifier::CStrArg; break; 23487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'u': k = ConversionSpecifier::uArg; break; 23587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'x': k = ConversionSpecifier::xArg; break; 23687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek // Mac OS X (unicode) specific 23787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'C': k = ConversionSpecifier::CArg; break; 23887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'S': k = ConversionSpecifier::UnicodeStrArg; break; 239c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek // Objective-C. 2404dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek case '@': k = ConversionSpecifier::ObjCObjArg; break; 241df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek // Glibc specific. 2424dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek case 'm': k = ConversionSpecifier::PrintErrno; break; 2438f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 244a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek FS.setConversionSpecifier(ConversionSpecifier(conversionPosition, k)); 24526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek 24626ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek if (k == ConversionSpecifier::InvalidSpecifier) { 24726ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg); 24826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek return false; // Keep processing format specifiers. 24926ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek } 2508f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return FormatSpecifierResult(Start, FS); 2518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} 2528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 25374d56a168966ff015824279a24aaf566180ed97dTed Kremenekbool clang::analyze_printf::ParseFormatString(FormatStringHandler &H, 254a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek const char *I, const char *E) { 2558f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Keep looking for a format specifier until we have exhausted the string. 2568f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek while (I != E) { 2578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E); 25826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // Did a fail-stop error of any kind occur when parsing the specifier? 25926ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // If so, don't do any more processing. 26026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek if (FSR.shouldStop()) 2618f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true;; 26226ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // Did we exhaust the string or encounter an error that 26326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // we can recover from? 2648f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (!FSR.hasValue()) 26526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek continue; 2668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // We have a format specifier. Pass it to the callback. 267a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek if (!H.HandleFormatSpecifier(FSR.getValue(), FSR.getStart(), 268a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek I - FSR.getStart())) 2694dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek return true; 2704e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 2714e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek assert(I == E && "Format string not exhausted"); 2728f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return false; 2738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} 2748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 2758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted KremenekFormatStringHandler::~FormatStringHandler() {} 27633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 27733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===// 2784e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods on ArgTypeResult. 2794e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 2804e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2814e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenekbool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { 2824e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek assert(isValid()); 2834e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2844e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == UnknownTy) 2854e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return true; 2864e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2874e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == SpecificTy) { 2884e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek argTy = C.getCanonicalType(argTy).getUnqualifiedType(); 2894e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2904e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (T == argTy) 2914e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return true; 2924e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2934e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) 2944e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek switch (BT->getKind()) { 2954e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek default: 2964e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek break; 2974e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Char_S: 2984e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::SChar: 2994e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.UnsignedCharTy; 3004e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Char_U: 3014e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::UChar: 3024e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.SignedCharTy; 3034e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Short: 3044e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.UnsignedShortTy; 3054e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::UShort: 3064e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.ShortTy; 3074e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Int: 3084e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.UnsignedIntTy; 3094e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::UInt: 3104e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.IntTy; 3114e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Long: 3124e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.UnsignedLongTy; 3134e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::ULong: 3144e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.LongTy; 3154e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::LongLong: 3164e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.UnsignedLongLongTy; 3174e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::ULongLong: 3184e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.LongLongTy; 3194e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 3204e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3214e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 3224e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 3234e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3244e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == CStrTy) { 3254e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek const PointerType *PT = argTy->getAs<PointerType>(); 3264e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (!PT) 3274e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 3284e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3294e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek QualType pointeeTy = PT->getPointeeType(); 3304e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3314e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) 3324e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek switch (BT->getKind()) { 3334e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Void: 3344e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Char_U: 3354e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::UChar: 3364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Char_S: 3374e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::SChar: 3384e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return true; 3394e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek default: 3404e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek break; 3414e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 3424e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3434e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 3444e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 3454e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3464e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == WCStrTy) { 3474e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek const PointerType *PT = argTy->getAs<PointerType>(); 3484e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (!PT) 3494e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 3504e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 35187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek QualType pointeeTy = 35287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); 35387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek 35487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek return pointeeTy == C.getWCharType(); 3554e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 3564e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3574e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 3584e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek} 3594e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3604e4b30ec62d78b24e6556fea2624855c193d0e3eTed KremenekQualType ArgTypeResult::getRepresentativeType(ASTContext &C) const { 3614e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek assert(isValid()); 3624e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == SpecificTy) 3634e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T; 3644e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == CStrTy) 3654e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return C.getPointerType(C.CharTy); 3664e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == WCStrTy) 36787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek return C.getPointerType(C.getWCharType()); 3684e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == ObjCPointerTy) 3694e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return C.ObjCBuiltinIdTy; 3704e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3714e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return QualType(); 3724e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek} 3734e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3744e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 3754e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods on OptionalAmount. 3764e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 3774e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3784e4b30ec62d78b24e6556fea2624855c193d0e3eTed KremenekArgTypeResult OptionalAmount::getArgType(ASTContext &Ctx) const { 3794e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return Ctx.IntTy; 3804e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek} 3814e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3824e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 38333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek// Methods on FormatSpecifier. 38433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===// 38533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 38633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted KremenekArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const { 38733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek if (!CS.consumesDataArgument()) 38833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult::Invalid(); 3894e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 39033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek if (CS.isIntArg()) 39133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek switch (LM) { 3924e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case AsLongDouble: 39333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult::Invalid(); 39433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case None: return Ctx.IntTy; 39533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsChar: return Ctx.SignedCharTy; 39633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsShort: return Ctx.ShortTy; 39733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsLong: return Ctx.LongTy; 39833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsLongLong: return Ctx.LongLongTy; 39933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsIntMax: 40033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: Return unknown for now. 40133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 40233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsSizeT: return Ctx.getSizeType(); 40333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsPtrDiff: return Ctx.getPointerDiffType(); 40433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek } 40533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 40633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek if (CS.isUIntArg()) 40733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek switch (LM) { 4084e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case AsLongDouble: 40933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult::Invalid(); 41033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case None: return Ctx.UnsignedIntTy; 41133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsChar: return Ctx.UnsignedCharTy; 41233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsShort: return Ctx.UnsignedShortTy; 41333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsLong: return Ctx.UnsignedLongTy; 41433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsLongLong: return Ctx.UnsignedLongLongTy; 41533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsIntMax: 41633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: Return unknown for now. 41733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 4184e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case AsSizeT: 41933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: How to get the corresponding unsigned 42033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // version of size_t? 42133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 42233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek case AsPtrDiff: 42333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: How to get the corresponding unsigned 42433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // version of ptrdiff_t? 42533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 42633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek } 4274e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 428f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek if (CS.isDoubleArg()) { 429f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek if (LM == AsLongDouble) 430f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek return Ctx.LongDoubleTy; 431c9a89fec60a20eb3269caa95eca048d45ab215adTed Kremenek return Ctx.DoubleTy; 432f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek } 43387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek 43487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek switch (CS.getKind()) { 43587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case ConversionSpecifier::CStrArg: 43687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek return ArgTypeResult(LM == AsWideChar ? ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy); 43787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case ConversionSpecifier::UnicodeStrArg: 43887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek // FIXME: This appears to be Mac OS X specific. 43987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek return ArgTypeResult::WCStrTy; 44087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case ConversionSpecifier::CArg: 44187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek return Ctx.WCharTy; 44287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek default: 44387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek break; 44487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek } 44587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek 44633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: Handle other cases. 44740888ada6022cfd4ab2a7c07ab276639860ffc5aTed Kremenek return ArgTypeResult(); 44833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek} 44933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 450