PrintfFormatString.cpp revision 876e994957472eda4b40136d4e1d6e08e2be338f
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" 173bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care#include "clang/AST/Type.h" 183bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care#include "llvm/Support/raw_ostream.h" 198f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 2033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenekusing clang::analyze_printf::ArgTypeResult; 21efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekusing clang::analyze_printf::FormatSpecifier; 2274d56a168966ff015824279a24aaf566180ed97dTed Kremenekusing clang::analyze_printf::FormatStringHandler; 23efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekusing clang::analyze_printf::OptionalAmount; 24efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekusing clang::analyze_printf::PositionContext; 253bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Careusing clang::analyze_printf::ConversionSpecifier; 263bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Careusing clang::analyze_printf::LengthModifier; 27efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 28808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenekusing namespace clang; 298f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 308f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremeneknamespace { 318f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekclass FormatSpecifierResult { 328f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FormatSpecifier FS; 338f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *Start; 3426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek bool Stop; 358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekpublic: 3626ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek FormatSpecifierResult(bool stop = false) 3726ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek : Start(0), Stop(stop) {} 388f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FormatSpecifierResult(const char *start, 39d2dcece5882215e92a80bff8a7b7fd2fd81d7086Ted Kremenek const FormatSpecifier &fs) 4026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek : FS(fs), Start(start), Stop(false) {} 418f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 424e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 438f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *getStart() const { return Start; } 4426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek bool shouldStop() const { return Stop; } 458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek bool hasValue() const { return Start != 0; } 468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const FormatSpecifier &getValue() const { 478f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek assert(hasValue()); 488f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return FS; 498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 50d2dcece5882215e92a80bff8a7b7fd2fd81d7086Ted Kremenek const FormatSpecifier &getValue() { return FS; } 518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}; 528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} // end anonymous namespace 538f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 548f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenektemplate <typename T> 558f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekclass UpdateOnReturn { 568f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek T &ValueToUpdate; 578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const T &ValueToCopy; 588f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekpublic: 598f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek UpdateOnReturn(T &valueToUpdate, const T &valueToCopy) 608f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {} 614e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 628f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ~UpdateOnReturn() { 638f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ValueToUpdate = ValueToCopy; 648f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 654e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek}; 664e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 674e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 684e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods for parsing format strings. 694e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 71efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic OptionalAmount ParseAmount(const char *&Beg, const char *E) { 728f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *I = Beg; 738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek UpdateOnReturn <const char*> UpdateBeg(Beg, I); 744e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek unsigned accumulator = 0; 76d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek bool hasDigits = false; 778f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 788f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek for ( ; I != E; ++I) { 798f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek char c = *I; 808f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (c >= '0' && c <= '9') { 81d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek hasDigits = true; 82fdb703ab3a3c28aeb53b3db4c54e14a30d78dc4eTed Kremenek accumulator = (accumulator * 10) + (c - '0'); 838f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek continue; 848f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 858f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 86d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek if (hasDigits) 873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, 0); 884e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 898f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 908f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 914e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 924e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return OptionalAmount(); 938f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} 948f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 95efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E, 96efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek unsigned &argIndex) { 97efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (*Beg == '*') { 98efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek ++Beg; 993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0); 100efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 101efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 102efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return ParseAmount(Beg, E); 103efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek} 104efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 105efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic OptionalAmount ParsePositionAmount(FormatStringHandler &H, 106efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *Start, 107efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *&Beg, const char *E, 108efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek PositionContext p) { 109efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (*Beg == '*') { 110efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *I = Beg + 1; 111efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const OptionalAmount &Amt = ParseAmount(I, E); 112efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 113efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) { 114efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek H.HandleInvalidPosition(Beg, I - Beg, p); 115efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return OptionalAmount(false); 116efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 117efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 118efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (I== E) { 119efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // No more characters left? 120efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 121efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return OptionalAmount(false); 122efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 123efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 124d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek assert(Amt.getHowSpecified() == OptionalAmount::Constant); 125d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek 126efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (*I == '$') { 1273bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Handle positional arguments 1283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 129d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek // Special case: '*0$', since this is an easy mistake. 130d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek if (Amt.getConstantAmount() == 0) { 131d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek H.HandleZeroPosition(Beg, I - Beg + 1); 132d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek return OptionalAmount(false); 133d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek } 134d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek 135efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *Tmp = Beg; 136efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek Beg = ++I; 137d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek 138efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1, 1393bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care Tmp, 1); 140efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 141efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 142efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek H.HandleInvalidPosition(Beg, I - Beg, p); 143efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return OptionalAmount(false); 144efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 145efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 146efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return ParseAmount(Beg, E); 147efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek} 148efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 149efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic bool ParsePrecision(FormatStringHandler &H, FormatSpecifier &FS, 150efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *Start, const char *&Beg, const char *E, 151efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek unsigned *argIndex) { 152efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (argIndex) { 153efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex)); 154efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 155efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek else { 156efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 157efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek analyze_printf::PrecisionPos); 158efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (Amt.isInvalid()) 159efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 160efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setPrecision(Amt); 161efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 162efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return false; 163efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek} 164efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 165efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic bool ParseFieldWidth(FormatStringHandler &H, FormatSpecifier &FS, 166efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *Start, const char *&Beg, const char *E, 167efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek unsigned *argIndex) { 168efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // FIXME: Support negative field widths. 169efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (argIndex) { 170efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex)); 171efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 172efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek else { 173efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 174efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek analyze_printf::FieldWidthPos); 175efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (Amt.isInvalid()) 176efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 177efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setFieldWidth(Amt); 178efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 179efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return false; 180efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek} 181efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 182efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 183efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic bool ParseArgPosition(FormatStringHandler &H, 184efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FormatSpecifier &FS, const char *Start, 185efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *&Beg, const char *E) { 186efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 187efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek using namespace clang::analyze_printf; 188efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *I = Beg; 189efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 190efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const OptionalAmount &Amt = ParseAmount(I, E); 191efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 192efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (I == E) { 193efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // No more characters left? 194efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 195efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 196efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 197efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 198efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') { 199d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek // Special case: '%0$', since this is an easy mistake. 200d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek if (Amt.getConstantAmount() == 0) { 201d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek H.HandleZeroPosition(Start, I - Start); 202d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek return true; 203d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek } 204d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek 205efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setArgIndex(Amt.getConstantAmount() - 1); 206efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setUsesPositionalArg(); 207efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // Update the caller's pointer if we decided to consume 208efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // these characters. 209efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek Beg = I; 210efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return false; 211efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 212efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 213efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return false; 214efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek} 215efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 216808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenekstatic FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H, 21774d56a168966ff015824279a24aaf566180ed97dTed Kremenek const char *&Beg, 2187f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek const char *E, 2197f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek unsigned &argIndex) { 2204e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2214b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenek using namespace clang::analyze_printf; 2224e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *I = Beg; 224c7ae51a3cd9460db8280e8623c90614f246e46d2Ted Kremenek const char *Start = 0; 2258f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek UpdateOnReturn <const char*> UpdateBeg(Beg, I); 2268f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 2278f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for a '%' character that indicates the start of a format specifier. 228e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek for ( ; I != E ; ++I) { 2298f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek char c = *I; 2308f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (c == '\0') { 2318f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Detect spurious null characters, which are likely errors. 2328f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek H.HandleNullChar(I); 2338f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2348f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (c == '%') { 236e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek Start = I++; // Record the start of the format specifier. 2378f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 2388f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2404e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2418f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No format specifier found? 2428f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (!Start) 2438f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return false; 2444e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 2468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 247808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 2488f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2504e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FormatSpecifier FS; 252efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (ParseArgPosition(H, FS, Start, I, E)) 253efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 254efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 255efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (I == E) { 256efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // No more characters left? 257efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 258efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 259efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 2604e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2618f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for flags (if any). 2628f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek bool hasMore = true; 2638f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek for ( ; I != E; ++I) { 2648f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek switch (*I) { 2658f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek default: hasMore = false; break; 2668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '-': FS.setIsLeftJustified(); break; 2678f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '+': FS.setHasPlusPrefix(); break; 2688f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case ' ': FS.setHasSpacePrefix(); break; 2698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '#': FS.setHasAlternativeForm(); break; 2708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '0': FS.setHasLeadingZeros(); break; 2718f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2728f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (!hasMore) 2738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 2744e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 2758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 2768f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 2778f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 278808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 2798f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2808f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2814e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2828f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for the field width (if any). 283efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (ParseFieldWidth(H, FS, Start, I, E, 284efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.usesPositionalArg() ? 0 : &argIndex)) 285efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 2864e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2878f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 2888f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 289808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 2908f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2914e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 2924e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2934e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek // Look for the precision (if any). 2948f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (*I == '.') { 295808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek ++I; 2968f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 297808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 2988f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2998f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 3004e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 301efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (ParsePrecision(H, FS, Start, I, E, 302efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.usesPositionalArg() ? 0 : &argIndex)) 303efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 3048f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 3058f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 3068f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 307808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 3088f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 3098f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 3108f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 3118f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 3128f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for the length modifier. 3133bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LengthModifier::Kind lmKind = LengthModifier::None; 3143bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care const char *lmPosition = I; 3158f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek switch (*I) { 3168f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek default: 3178f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 3188f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case 'h': 3198f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ++I; 3203bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care lmKind = (I != E && *I == 'h') ? 3213bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care ++I, LengthModifier::AsChar : LengthModifier::AsShort; 3228f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 3238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case 'l': 3248f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ++I; 3253bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care lmKind = (I != E && *I == 'l') ? 3263bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care ++I, LengthModifier::AsLongLong : LengthModifier::AsLong; 3278f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 3283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; 3293bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; 3303bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; 3313bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; 3323bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case 'q': lmKind = LengthModifier::AsLongLong; ++I; break; 3338f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 3343bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LengthModifier lm(lmPosition, lmKind); 3358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FS.setLengthModifier(lm); 3364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3378f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 3388f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 339808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 3408f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 3418f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 342df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek 3434dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek if (*I == '\0') { 344df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek // Detect spurious null characters, which are likely errors. 345df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek H.HandleNullChar(I); 346df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek return true; 3474dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek } 3484e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Finally, look for the conversion specifier. 350a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek const char *conversionPosition = I++; 35126ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 352a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek switch (*conversionPosition) { 3538f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek default: 35426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek break; 355c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek // C99: 7.19.6.1 (section 8). 35687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case '%': k = ConversionSpecifier::PercentArg; break; 35787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'A': k = ConversionSpecifier::AArg; break; 358a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'E': k = ConversionSpecifier::EArg; break; 35987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'F': k = ConversionSpecifier::FArg; break; 360a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'G': k = ConversionSpecifier::GArg; break; 36187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'X': k = ConversionSpecifier::XArg; break; 362a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'a': k = ConversionSpecifier::aArg; break; 363a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'c': k = ConversionSpecifier::IntAsCharArg; break; 36487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'd': k = ConversionSpecifier::dArg; break; 36587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'e': k = ConversionSpecifier::eArg; break; 36687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'f': k = ConversionSpecifier::fArg; break; 36787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'g': k = ConversionSpecifier::gArg; break; 36887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'i': k = ConversionSpecifier::iArg; break; 369a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'n': k = ConversionSpecifier::OutIntPtrArg; break; 37087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'o': k = ConversionSpecifier::oArg; break; 37187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'p': k = ConversionSpecifier::VoidPtrArg; break; 37287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 's': k = ConversionSpecifier::CStrArg; break; 37387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'u': k = ConversionSpecifier::uArg; break; 37487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'x': k = ConversionSpecifier::xArg; break; 37587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek // Mac OS X (unicode) specific 37687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'C': k = ConversionSpecifier::CArg; break; 37787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'S': k = ConversionSpecifier::UnicodeStrArg; break; 378c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek // Objective-C. 3794dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek case '@': k = ConversionSpecifier::ObjCObjArg; break; 380df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek // Glibc specific. 3814dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek case 'm': k = ConversionSpecifier::PrintErrno; break; 3828f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 3837f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek ConversionSpecifier CS(conversionPosition, k); 3847f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek FS.setConversionSpecifier(CS); 385efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (CS.consumesDataArgument() && !FS.usesPositionalArg()) 3867f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek FS.setArgIndex(argIndex++); 38726ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek 38826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek if (k == ConversionSpecifier::InvalidSpecifier) { 3897f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek // Assume the conversion takes one argument. 3907f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek return !H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg); 39126ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek } 3928f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return FormatSpecifierResult(Start, FS); 3938f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} 3948f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 39574d56a168966ff015824279a24aaf566180ed97dTed Kremenekbool clang::analyze_printf::ParseFormatString(FormatStringHandler &H, 396a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek const char *I, const char *E) { 3977f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek 3987f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek unsigned argIndex = 0; 3997f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek 4008f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Keep looking for a format specifier until we have exhausted the string. 4018f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek while (I != E) { 4027f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E, argIndex); 40326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // Did a fail-stop error of any kind occur when parsing the specifier? 40426ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // If so, don't do any more processing. 40526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek if (FSR.shouldStop()) 4068f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true;; 40726ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // Did we exhaust the string or encounter an error that 40826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // we can recover from? 4098f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (!FSR.hasValue()) 41026ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek continue; 4118f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // We have a format specifier. Pass it to the callback. 412a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek if (!H.HandleFormatSpecifier(FSR.getValue(), FSR.getStart(), 413a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek I - FSR.getStart())) 4144dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek return true; 4154e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 4164e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek assert(I == E && "Format string not exhausted"); 4178f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return false; 4188f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} 4198f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 4208f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted KremenekFormatStringHandler::~FormatStringHandler() {} 42133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 42233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===// 4234e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods on ArgTypeResult. 4244e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 4254e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4264e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenekbool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { 4274e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek assert(isValid()); 4284e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4294e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == UnknownTy) 4304e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return true; 4314e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4324e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == SpecificTy) { 4334e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek argTy = C.getCanonicalType(argTy).getUnqualifiedType(); 4344e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4354e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (T == argTy) 4364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return true; 4374e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4384e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) 4394e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek switch (BT->getKind()) { 4404e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek default: 4414e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek break; 4424e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Char_S: 4434e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::SChar: 4444e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.UnsignedCharTy; 4454e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Char_U: 4464e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::UChar: 4474e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.SignedCharTy; 4484e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Short: 4494e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.UnsignedShortTy; 4504e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::UShort: 4514e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.ShortTy; 4524e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Int: 4534e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.UnsignedIntTy; 4544e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::UInt: 4554e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.IntTy; 4564e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Long: 4574e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.UnsignedLongTy; 4584e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::ULong: 4594e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.LongTy; 4604e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::LongLong: 4614e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.UnsignedLongLongTy; 4624e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::ULongLong: 4634e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T == C.LongLongTy; 4644e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 4654e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4664e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 4674e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 4684e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4694e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == CStrTy) { 4704e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek const PointerType *PT = argTy->getAs<PointerType>(); 4714e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (!PT) 4724e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 4734e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4744e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek QualType pointeeTy = PT->getPointeeType(); 4754e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4764e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) 4774e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek switch (BT->getKind()) { 4784e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Void: 4794e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Char_U: 4804e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::UChar: 4814e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::Char_S: 4824e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek case BuiltinType::SChar: 4834e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return true; 4844e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek default: 4854e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek break; 4864e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 4874e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4884e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 4894e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 4904e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4914e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == WCStrTy) { 4924e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek const PointerType *PT = argTy->getAs<PointerType>(); 4934e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (!PT) 4944e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 4954e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 49687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek QualType pointeeTy = 49787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); 49887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek 49987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek return pointeeTy == C.getWCharType(); 5004e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 5014e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 5024e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 5034e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek} 5044e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 5054e4b30ec62d78b24e6556fea2624855c193d0e3eTed KremenekQualType ArgTypeResult::getRepresentativeType(ASTContext &C) const { 5064e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek assert(isValid()); 5074e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == SpecificTy) 5084e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return T; 5094e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == CStrTy) 5104e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return C.getPointerType(C.CharTy); 5114e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == WCStrTy) 51287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek return C.getPointerType(C.getWCharType()); 5134e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek if (K == ObjCPointerTy) 5144e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return C.ObjCBuiltinIdTy; 5154e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 5164e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return QualType(); 5174e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek} 5184e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 5194e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 5204e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods on OptionalAmount. 5214e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 5224e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 5234e4b30ec62d78b24e6556fea2624855c193d0e3eTed KremenekArgTypeResult OptionalAmount::getArgType(ASTContext &Ctx) const { 5244e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return Ctx.IntTy; 5254e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek} 5264e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 5274e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 5283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care// Methods on ConversionSpecifier. 5293bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 5303bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Careconst char *ConversionSpecifier::toString() const { 5313bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (kind) { 5323bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case dArg: return "d"; 5333bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case iArg: return "i"; 5343bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case oArg: return "o"; 5353bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case uArg: return "u"; 5363bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case xArg: return "x"; 5373bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case XArg: return "X"; 5383bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case fArg: return "f"; 5393bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case FArg: return "F"; 5403bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case eArg: return "e"; 5413bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case EArg: return "E"; 5423bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case gArg: return "g"; 5433bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case GArg: return "G"; 5443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case aArg: return "a"; 5453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AArg: return "A"; 5463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case IntAsCharArg: return "c"; 5473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case CStrArg: return "s"; 5483bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case VoidPtrArg: return "p"; 5493bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case OutIntPtrArg: return "n"; 5503bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case PercentArg: return "%"; 5513bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case InvalidSpecifier: return NULL; 5523bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // MacOS X unicode extensions. 5543bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case CArg: return "C"; 5553bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case UnicodeStrArg: return "S"; 5563bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5573bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Objective-C specific specifiers. 5583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case ObjCObjArg: return "@"; 5593bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5603bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // GlibC specific specifiers. 5613bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case PrintErrno: return "m"; 5623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 5633bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return NULL; 5643bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care} 5653bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5663bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 5673bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care// Methods on LengthModifier. 5683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 5693bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5703bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Careconst char *LengthModifier::toString() const { 5713bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (kind) { 5723bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsChar: 5733bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "hh"; 5743bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsShort: 5753bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "h"; 5763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsLong: // or AsWideChar 5773bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "l"; 5783bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsLongLong: 5793bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "ll"; 5803bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsIntMax: 5813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "j"; 5823bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsSizeT: 5833bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "z"; 5843bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsPtrDiff: 5853bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "t"; 5863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsLongDouble: 5873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "L"; 5883bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case None: 5893bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return ""; 5903bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 5913bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return NULL; 5923bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care} 5933bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5943bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 5953bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care// Methods on OptionalAmount. 5963bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 5973bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5983bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Carevoid OptionalAmount::toString(llvm::raw_ostream &os) const { 5993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (hs) { 6003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case Invalid: 6013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case NotSpecified: 6023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return; 6033bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case Arg: 6043bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (usesPositionalArg()) 6053bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << ".*" << getPositionalArgIndex() << "$"; 6063bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care else 6073bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << ".*"; 6083bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 6093bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case Constant: 6103bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << "." << amt; 6113bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 6123bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 6133bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care} 6143bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 6153bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 61633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek// Methods on FormatSpecifier. 61733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===// 61833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 61933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted KremenekArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const { 62033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek if (!CS.consumesDataArgument()) 62133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult::Invalid(); 6224e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 62333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek if (CS.isIntArg()) 6243bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (LM.getKind()) { 6253bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLongDouble: 62633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult::Invalid(); 6273bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::None: return Ctx.IntTy; 6283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsChar: return Ctx.SignedCharTy; 6293bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsShort: return Ctx.ShortTy; 6303bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLong: return Ctx.LongTy; 6313bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLongLong: return Ctx.LongLongTy; 6323bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsIntMax: 63333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: Return unknown for now. 63433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 6353bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsSizeT: return Ctx.getSizeType(); 6363bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsPtrDiff: return Ctx.getPointerDiffType(); 63733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek } 63833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 63933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek if (CS.isUIntArg()) 6403bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (LM.getKind()) { 6413bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLongDouble: 64233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult::Invalid(); 6433bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::None: return Ctx.UnsignedIntTy; 6443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsChar: return Ctx.UnsignedCharTy; 6453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsShort: return Ctx.UnsignedShortTy; 6463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLong: return Ctx.UnsignedLongTy; 6473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy; 6483bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsIntMax: 64933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: Return unknown for now. 65033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 6513bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsSizeT: 65233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: How to get the corresponding unsigned 65333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // version of size_t? 65433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 6553bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsPtrDiff: 65633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: How to get the corresponding unsigned 65733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // version of ptrdiff_t? 65833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 65933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek } 6604e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 661f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek if (CS.isDoubleArg()) { 6623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (LM.getKind() == LengthModifier::AsLongDouble) 663f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek return Ctx.LongDoubleTy; 664c9a89fec60a20eb3269caa95eca048d45ab215adTed Kremenek return Ctx.DoubleTy; 665f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek } 6667f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek 66787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek switch (CS.getKind()) { 66887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case ConversionSpecifier::CStrArg: 6693bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ? 6703bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy); 67187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case ConversionSpecifier::UnicodeStrArg: 67287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek // FIXME: This appears to be Mac OS X specific. 67387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek return ArgTypeResult::WCStrTy; 67487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case ConversionSpecifier::CArg: 6757f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek return Ctx.WCharTy; 67687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek default: 67787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek break; 67887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek } 6797f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek 68033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: Handle other cases. 68140888ada6022cfd4ab2a7c07ab276639860ffc5aTed Kremenek return ArgTypeResult(); 68233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek} 68333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 6843bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Carebool FormatSpecifier::fixType(QualType QT) { 6853bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Handle strings first (char *, wchar_t *) 6863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { 6873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::CStrArg); 6883bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 689876e994957472eda4b40136d4e1d6e08e2be338fTom Care // Disable irrelevant flags 690876e994957472eda4b40136d4e1d6e08e2be338fTom Care HasAlternativeForm = 0; 691876e994957472eda4b40136d4e1d6e08e2be338fTom Care HasLeadingZeroes = 0; 692876e994957472eda4b40136d4e1d6e08e2be338fTom Care 6933bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Set the long length modifier for wide characters 6943bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (QT->getPointeeType()->isWideCharType()) 6953bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LM.setKind(LengthModifier::AsWideChar); 6963bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 6973bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return true; 6983bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 6993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // We can only work with builtin types. 7013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (!QT->isBuiltinType()) 7023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return false; 7033bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7043bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Everything else should be a base type 7053bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care const BuiltinType *BT = QT->getAs<BuiltinType>(); 706876e994957472eda4b40136d4e1d6e08e2be338fTom Care 7073bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Set length modifier 7083bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (BT->getKind()) { 7093bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care default: 710876e994957472eda4b40136d4e1d6e08e2be338fTom Care // The rest of the conversions are either optional or for non-builtin types 711876e994957472eda4b40136d4e1d6e08e2be338fTom Care LM.setKind(LengthModifier::None); 7123bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 713876e994957472eda4b40136d4e1d6e08e2be338fTom Care 7143bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::WChar: 7153bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::Long: 7163bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::ULong: 7173bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LM.setKind(LengthModifier::AsLong); 7183bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 7193bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7203bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::LongLong: 7213bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::ULongLong: 7223bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LM.setKind(LengthModifier::AsLongLong); 7233bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 7243bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7253bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::LongDouble: 7263bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LM.setKind(LengthModifier::AsLongDouble); 7273bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 7283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7293bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7303bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Set conversion specifier and disable any flags which do not apply to it. 7313bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (QT->isAnyCharacterType()) { 7323bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::IntAsCharArg); 7333bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care Precision.setHowSpecified(OptionalAmount::NotSpecified); 7343bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasAlternativeForm = 0; 7353bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasLeadingZeroes = 0; 7363bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7373bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Test for Floating type first as LongDouble can pass isUnsignedIntegerType 7383bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care else if (QT->isFloatingType()) { 7393bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::fArg); 7403bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7413bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care else if (QT->isPointerType()) { 7423bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::VoidPtrArg); 7433bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care Precision.setHowSpecified(OptionalAmount::NotSpecified); 7443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasAlternativeForm = 0; 7453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasLeadingZeroes = 0; 7463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care else if (QT->isSignedIntegerType()) { 7483bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::dArg); 7493bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasAlternativeForm = 0; 7503bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 751c8c4b4088cf0b3afeda425b25fa7c77d3873b12cDouglas Gregor else if (QT->isUnsignedIntegerType()) { 7523bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::uArg); 7533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasAlternativeForm = 0; 7543bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7553bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care else { 7563bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return false; 7573bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7593bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return true; 7603bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care} 7613bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Carevoid FormatSpecifier::toString(llvm::raw_ostream &os) const { 7633bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Whilst some features have no defined order, we are using the order 7643bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // appearing in the C99 standard (ISO/IEC 9899:1999 (E) �7.19.6.1) 7653bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << "%"; 7663bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7673bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Positional args 7683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (usesPositionalArg()) { 7693bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << getPositionalArgIndex() << "$"; 7703bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7713bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7723bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Conversion flags 7733bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (IsLeftJustified) os << "-"; 7743bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (HasPlusPrefix) os << "+"; 7753bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (HasSpacePrefix) os << " "; 7763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (HasAlternativeForm) os << "#"; 7773bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (HasLeadingZeroes) os << "0"; 7783bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7793bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Minimum field width 7803bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care FieldWidth.toString(os); 7813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Precision 7823bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care Precision.toString(os); 7833bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Length modifier 7843bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << LM.toString(); 7853bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Conversion specifier 7863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << CS.toString(); 7873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care} 788