PrintfFormatString.cpp revision 13927a431dd733336cfd664bf0840747a71b0a43
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 428f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *getStart() const { return Start; } 4326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek bool shouldStop() const { return Stop; } 448f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek bool hasValue() const { return Start != 0; } 458f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const FormatSpecifier &getValue() const { 468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek assert(hasValue()); 478f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return FS; 488f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 49d2dcece5882215e92a80bff8a7b7fd2fd81d7086Ted Kremenek const FormatSpecifier &getValue() { return FS; } 508f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek}; 518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} // end anonymous namespace 528f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 538f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenektemplate <typename T> 548f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekclass UpdateOnReturn { 558f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek T &ValueToUpdate; 568f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const T &ValueToCopy; 578f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenekpublic: 588f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek UpdateOnReturn(T &valueToUpdate, const T &valueToCopy) 598f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek : ValueToUpdate(valueToUpdate), ValueToCopy(valueToCopy) {} 604e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 618f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ~UpdateOnReturn() { 628f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ValueToUpdate = ValueToCopy; 638f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 644e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek}; 654e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 664e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 674e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods for parsing format strings. 684e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 70efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic OptionalAmount ParseAmount(const char *&Beg, const char *E) { 718f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *I = Beg; 728f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek UpdateOnReturn <const char*> UpdateBeg(Beg, I); 734e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek unsigned accumulator = 0; 75d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek bool hasDigits = false; 768f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 778f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek for ( ; I != E; ++I) { 788f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek char c = *I; 798f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (c >= '0' && c <= '9') { 80d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek hasDigits = true; 81fdb703ab3a3c28aeb53b3db4c54e14a30d78dc4eTed Kremenek accumulator = (accumulator * 10) + (c - '0'); 828f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek continue; 838f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 848f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 85d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek if (hasDigits) 863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, 0); 874e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 888f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 898f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 904e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 914e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return OptionalAmount(); 928f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} 938f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 94efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic OptionalAmount ParseNonPositionAmount(const char *&Beg, const char *E, 95efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek unsigned &argIndex) { 96efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (*Beg == '*') { 97efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek ++Beg; 983bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0); 99efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 100efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 101efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return ParseAmount(Beg, E); 102efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek} 103efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 104efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic OptionalAmount ParsePositionAmount(FormatStringHandler &H, 105efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *Start, 106efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *&Beg, const char *E, 107efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek PositionContext p) { 108efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (*Beg == '*') { 109efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *I = Beg + 1; 110efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const OptionalAmount &Amt = ParseAmount(I, E); 111efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 112efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) { 113efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek H.HandleInvalidPosition(Beg, I - Beg, p); 114efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return OptionalAmount(false); 115efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 116efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 117efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (I== E) { 118efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // No more characters left? 119efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 120efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return OptionalAmount(false); 121efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 122efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 123d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek assert(Amt.getHowSpecified() == OptionalAmount::Constant); 124d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek 125efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (*I == '$') { 1263bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Handle positional arguments 1273bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 128d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek // Special case: '*0$', since this is an easy mistake. 129d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek if (Amt.getConstantAmount() == 0) { 130d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek H.HandleZeroPosition(Beg, I - Beg + 1); 131d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek return OptionalAmount(false); 132d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek } 133d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek 134efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *Tmp = Beg; 135efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek Beg = ++I; 136d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek 137efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1, 1383bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care Tmp, 1); 139efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 140efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 141efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek H.HandleInvalidPosition(Beg, I - Beg, p); 142efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return OptionalAmount(false); 143efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 144efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 145efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return ParseAmount(Beg, E); 146efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek} 147efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 148efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic bool ParsePrecision(FormatStringHandler &H, FormatSpecifier &FS, 149efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *Start, const char *&Beg, const char *E, 150efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek unsigned *argIndex) { 151efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (argIndex) { 152efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex)); 153efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 154efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek else { 155efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 156efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek analyze_printf::PrecisionPos); 157efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (Amt.isInvalid()) 158efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 159efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setPrecision(Amt); 160efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 161efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return false; 162efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek} 163efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 164efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic bool ParseFieldWidth(FormatStringHandler &H, FormatSpecifier &FS, 165efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *Start, const char *&Beg, const char *E, 166efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek unsigned *argIndex) { 167efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // FIXME: Support negative field widths. 168efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (argIndex) { 169efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex)); 170efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 171efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek else { 172efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E, 173efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek analyze_printf::FieldWidthPos); 174efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (Amt.isInvalid()) 175efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 176efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setFieldWidth(Amt); 177efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 178efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return false; 179efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek} 180efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 181efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenekstatic bool ParseArgPosition(FormatStringHandler &H, 182efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FormatSpecifier &FS, const char *Start, 183efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *&Beg, const char *E) { 184efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 185efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek using namespace clang::analyze_printf; 186efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const char *I = Beg; 187efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 188efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek const OptionalAmount &Amt = ParseAmount(I, E); 189efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 190efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (I == E) { 191efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // No more characters left? 192efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 193efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 194efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 195efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 196efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') { 197d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek // Special case: '%0$', since this is an easy mistake. 198d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek if (Amt.getConstantAmount() == 0) { 199d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek H.HandleZeroPosition(Start, I - Start); 200d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek return true; 201d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek } 202d49d87719b8e272134e76601e3efc0197785aa8aTed Kremenek 203efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setArgIndex(Amt.getConstantAmount() - 1); 204efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.setUsesPositionalArg(); 205efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // Update the caller's pointer if we decided to consume 206efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // these characters. 207efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek Beg = I; 208efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return false; 209efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 210efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 211efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return false; 212efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek} 213efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 214808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenekstatic FormatSpecifierResult ParseFormatSpecifier(FormatStringHandler &H, 21574d56a168966ff015824279a24aaf566180ed97dTed Kremenek const char *&Beg, 2167f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek const char *E, 2177f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek unsigned &argIndex) { 2184e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2194b220fae2f525fda39685ddfa7759950db1185e2Ted Kremenek using namespace clang::analyze_printf; 2204e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2218f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek const char *I = Beg; 222c7ae51a3cd9460db8280e8623c90614f246e46d2Ted Kremenek const char *Start = 0; 2238f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek UpdateOnReturn <const char*> UpdateBeg(Beg, I); 2248f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 2258f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for a '%' character that indicates the start of a format specifier. 226e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek for ( ; I != E ; ++I) { 2278f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek char c = *I; 2288f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (c == '\0') { 2298f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Detect spurious null characters, which are likely errors. 2308f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek H.HandleNullChar(I); 2318f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2328f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2338f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (c == '%') { 234e729acbba75903f42e79e72e46cdebe3f4c35521Ted Kremenek Start = I++; // Record the start of the format specifier. 2358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 2368f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2378f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2384e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No format specifier found? 2408f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (!Start) 2418f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return false; 2424e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2438f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 2448f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 245808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 2468f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2478f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2484e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2498f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FormatSpecifier FS; 250efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (ParseArgPosition(H, FS, Start, I, E)) 251efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 252efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek 253efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (I == E) { 254efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek // No more characters left? 255efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 256efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 257efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek } 2584e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2598f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for flags (if any). 2608f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek bool hasMore = true; 2618f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek for ( ; I != E; ++I) { 2628f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek switch (*I) { 2638f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek default: hasMore = false; break; 2648f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '-': FS.setIsLeftJustified(); break; 2658f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '+': FS.setHasPlusPrefix(); break; 2668f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case ' ': FS.setHasSpacePrefix(); break; 2678f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '#': FS.setHasAlternativeForm(); break; 2688f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case '0': FS.setHasLeadingZeros(); break; 2698f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2708f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (!hasMore) 2718f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 2724e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 2738f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 2748f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 2758f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 276808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 2778f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2788f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2794e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2808f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for the field width (if any). 281efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (ParseFieldWidth(H, FS, Start, I, E, 282efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.usesPositionalArg() ? 0 : &argIndex)) 283efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 2844e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2858f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 2868f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 287808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 2888f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2894e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 2904e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 2914e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek // Look for the precision (if any). 2928f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (*I == '.') { 293808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek ++I; 2948f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 295808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 2968f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 2978f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 2984e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 299efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (ParsePrecision(H, FS, Start, I, E, 300efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek FS.usesPositionalArg() ? 0 : &argIndex)) 301efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek return true; 3028f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 3038f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 3048f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 305808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 3068f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 3078f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 3088f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 3098f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 3108f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Look for the length modifier. 3113bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LengthModifier::Kind lmKind = LengthModifier::None; 3123bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care const char *lmPosition = I; 3138f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek switch (*I) { 3148f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek default: 3158f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 3168f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case 'h': 3178f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ++I; 3183bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care lmKind = (I != E && *I == 'h') ? 3193bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care ++I, LengthModifier::AsChar : LengthModifier::AsShort; 3208f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 3218f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek case 'l': 3228f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek ++I; 3233bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care lmKind = (I != E && *I == 'l') ? 3243bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care ++I, LengthModifier::AsLongLong : LengthModifier::AsLong; 3258f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek break; 3263bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case 'j': lmKind = LengthModifier::AsIntMax; ++I; break; 3273bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case 'z': lmKind = LengthModifier::AsSizeT; ++I; break; 3283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case 't': lmKind = LengthModifier::AsPtrDiff; ++I; break; 3293bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break; 3303bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case 'q': lmKind = LengthModifier::AsLongLong; ++I; break; 3318f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 3323bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LengthModifier lm(lmPosition, lmKind); 3338f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek FS.setLengthModifier(lm); 3344e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3358f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (I == E) { 3368f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // No more characters left? 337808015a18bd97781ce437831a95a92fdfc8d5136Ted Kremenek H.HandleIncompleteFormatSpecifier(Start, E - Start); 3388f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true; 3398f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 340df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek 3414dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek if (*I == '\0') { 342df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek // Detect spurious null characters, which are likely errors. 343df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek H.HandleNullChar(I); 344df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek return true; 3454dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek } 3464e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 3478f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Finally, look for the conversion specifier. 348a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek const char *conversionPosition = I++; 34926ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier; 350a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek switch (*conversionPosition) { 3518f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek default: 35226ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek break; 353c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek // C99: 7.19.6.1 (section 8). 35487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case '%': k = ConversionSpecifier::PercentArg; break; 35587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'A': k = ConversionSpecifier::AArg; break; 356a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'E': k = ConversionSpecifier::EArg; break; 35787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'F': k = ConversionSpecifier::FArg; break; 358a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'G': k = ConversionSpecifier::GArg; break; 35987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'X': k = ConversionSpecifier::XArg; break; 360a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'a': k = ConversionSpecifier::aArg; break; 361a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'c': k = ConversionSpecifier::IntAsCharArg; break; 36287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'd': k = ConversionSpecifier::dArg; break; 36387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'e': k = ConversionSpecifier::eArg; break; 36487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'f': k = ConversionSpecifier::fArg; break; 36587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'g': k = ConversionSpecifier::gArg; break; 36687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'i': k = ConversionSpecifier::iArg; break; 367a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek case 'n': k = ConversionSpecifier::OutIntPtrArg; break; 36887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'o': k = ConversionSpecifier::oArg; break; 36987260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'p': k = ConversionSpecifier::VoidPtrArg; break; 37087260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 's': k = ConversionSpecifier::CStrArg; break; 37187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'u': k = ConversionSpecifier::uArg; break; 37287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'x': k = ConversionSpecifier::xArg; break; 37387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek // Mac OS X (unicode) specific 37487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'C': k = ConversionSpecifier::CArg; break; 37587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case 'S': k = ConversionSpecifier::UnicodeStrArg; break; 376c7cbb9bf8e0bf8c3191ef0b782ec198c433d2a4eTed Kremenek // Objective-C. 3774dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek case '@': k = ConversionSpecifier::ObjCObjArg; break; 378df17f9d95ba03ba41d8d39ccb688a4eb2ee00e9aTed Kremenek // Glibc specific. 3794dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek case 'm': k = ConversionSpecifier::PrintErrno; break; 3808f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek } 3817f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek ConversionSpecifier CS(conversionPosition, k); 3827f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek FS.setConversionSpecifier(CS); 383efaff195ba1fa55b6fe0b0b2435b81451387d241Ted Kremenek if (CS.consumesDataArgument() && !FS.usesPositionalArg()) 3847f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek FS.setArgIndex(argIndex++); 38526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek 38626ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek if (k == ConversionSpecifier::InvalidSpecifier) { 3877f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek // Assume the conversion takes one argument. 3887f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek return !H.HandleInvalidConversionSpecifier(FS, Beg, I - Beg); 38926ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek } 3908f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return FormatSpecifierResult(Start, FS); 3918f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} 3928f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 39374d56a168966ff015824279a24aaf566180ed97dTed Kremenekbool clang::analyze_printf::ParseFormatString(FormatStringHandler &H, 394a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek const char *I, const char *E) { 3957f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek 3967f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek unsigned argIndex = 0; 3977f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek 3988f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // Keep looking for a format specifier until we have exhausted the string. 3998f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek while (I != E) { 4007f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek const FormatSpecifierResult &FSR = ParseFormatSpecifier(H, I, E, argIndex); 40126ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // Did a fail-stop error of any kind occur when parsing the specifier? 40226ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // If so, don't do any more processing. 40326ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek if (FSR.shouldStop()) 4048f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return true;; 40526ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // Did we exhaust the string or encounter an error that 40626ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek // we can recover from? 4078f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek if (!FSR.hasValue()) 40826ac2e07b46bfb4d4f00752c96481c0a98c79c69Ted Kremenek continue; 4098f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek // We have a format specifier. Pass it to the callback. 410a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek if (!H.HandleFormatSpecifier(FSR.getValue(), FSR.getStart(), 411a8d8fec7876666d90bb2a144d3b832b2d89a088aTed Kremenek I - FSR.getStart())) 4124dcb18ff9d92c66c78077ac5cae4b83af37292e4Ted Kremenek return true; 4134e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 4144e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek assert(I == E && "Format string not exhausted"); 4158f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek return false; 4168f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek} 4178f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted Kremenek 4188f0a1c73fd2b83afd4b1fce6f964535b51d13659Ted KremenekFormatStringHandler::~FormatStringHandler() {} 41933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 42033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===// 4214e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods on ArgTypeResult. 4224e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 4234e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4244e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenekbool ArgTypeResult::matchesType(ASTContext &C, QualType argTy) const { 42513927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek switch (K) { 42613927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case InvalidTy: 42713927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek assert(false && "ArgTypeResult must be valid"); 4284e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return true; 4294e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 43013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case UnknownTy: 43113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return true; 4324e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 43313927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case SpecificTy: { 43413927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek argTy = C.getCanonicalType(argTy).getUnqualifiedType(); 43513927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek if (T == argTy) 43613927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return true; 43713927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek if (const BuiltinType *BT = argTy->getAs<BuiltinType>()) 43813927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek switch (BT->getKind()) { 43913927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek default: 44013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek break; 44113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::Char_S: 44213927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::SChar: 44313927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T == C.UnsignedCharTy; 44413927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::Char_U: 44513927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::UChar: 44613927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T == C.SignedCharTy; 44713927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::Short: 44813927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T == C.UnsignedShortTy; 44913927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::UShort: 45013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T == C.ShortTy; 45113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::Int: 45213927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T == C.UnsignedIntTy; 45313927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::UInt: 45413927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T == C.IntTy; 45513927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::Long: 45613927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T == C.UnsignedLongTy; 45713927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::ULong: 45813927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T == C.LongTy; 45913927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::LongLong: 46013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T == C.UnsignedLongLongTy; 46113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::ULongLong: 46213927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T == C.LongLongTy; 46313927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek } 4644e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 46513927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek } 4664e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 46713927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case CStrTy: { 46813927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek const PointerType *PT = argTy->getAs<PointerType>(); 46913927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek if (!PT) 47013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return false; 47113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek QualType pointeeTy = PT->getPointeeType(); 47213927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>()) 47313927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek switch (BT->getKind()) { 47413927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::Void: 47513927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::Char_U: 47613927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::UChar: 47713927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::Char_S: 47813927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case BuiltinType::SChar: 47913927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return true; 48013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek default: 48113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek break; 48213927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek } 4834e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 4844e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 48513927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek } 4864e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 48713927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case WCStrTy: { 48813927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek const PointerType *PT = argTy->getAs<PointerType>(); 48913927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek if (!PT) 49013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return false; 49113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek QualType pointeeTy = 49213927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType(); 49313927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return pointeeTy == C.getWCharType(); 49413927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek } 49587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek 49613927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case CPointerTy: 49713927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return argTy->getAs<PointerType>() != NULL || 49813927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek argTy->getAs<ObjCObjectPointerType>() != NULL; 49913927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek 50013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case ObjCPointerTy: 50113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return argTy->getAs<ObjCObjectPointerType>() != NULL; 5024e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek } 5034e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 50413927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek // FIXME: Should be unreachable, but Clang is currently emitting 50513927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek // a warning. 5064e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return false; 5074e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek} 5084e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 5094e4b30ec62d78b24e6556fea2624855c193d0e3eTed KremenekQualType ArgTypeResult::getRepresentativeType(ASTContext &C) const { 51013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek switch (K) { 51113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case InvalidTy: 51213927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek assert(false && "No representative type for Invalid ArgTypeResult"); 51313927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek // Fall-through. 51413927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case UnknownTy: 51513927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return QualType(); 51613927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case SpecificTy: 51713927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return T; 51813927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case CStrTy: 51913927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return C.getPointerType(C.CharTy); 52013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case WCStrTy: 52113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return C.getPointerType(C.getWCharType()); 52213927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case ObjCPointerTy: 52313927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return C.ObjCBuiltinIdTy; 52413927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case CPointerTy: 52513927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return C.VoidPtrTy; 52613927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek } 52713927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek 52813927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek // FIXME: Should be unreachable, but Clang is currently emitting 52913927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek // a warning. 5304e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return QualType(); 5314e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek} 5324e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 5334e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 5344e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek// Methods on OptionalAmount. 5354e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 5364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 5374e4b30ec62d78b24e6556fea2624855c193d0e3eTed KremenekArgTypeResult OptionalAmount::getArgType(ASTContext &Ctx) const { 5384e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek return Ctx.IntTy; 5394e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek} 5404e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 5414e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek//===----------------------------------------------------------------------===// 5423bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care// Methods on ConversionSpecifier. 5433bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 5443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Careconst char *ConversionSpecifier::toString() const { 5453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (kind) { 5463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case dArg: return "d"; 5473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case iArg: return "i"; 5483bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case oArg: return "o"; 5493bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case uArg: return "u"; 5503bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case xArg: return "x"; 5513bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case XArg: return "X"; 5523bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case fArg: return "f"; 5533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case FArg: return "F"; 5543bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case eArg: return "e"; 5553bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case EArg: return "E"; 5563bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case gArg: return "g"; 5573bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case GArg: return "G"; 5583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case aArg: return "a"; 5593bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AArg: return "A"; 5603bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case IntAsCharArg: return "c"; 5613bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case CStrArg: return "s"; 5623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case VoidPtrArg: return "p"; 5633bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case OutIntPtrArg: return "n"; 5643bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case PercentArg: return "%"; 5653bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case InvalidSpecifier: return NULL; 5663bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5673bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // MacOS X unicode extensions. 5683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case CArg: return "C"; 5693bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case UnicodeStrArg: return "S"; 5703bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5713bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Objective-C specific specifiers. 5723bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case ObjCObjArg: return "@"; 5733bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5743bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // GlibC specific specifiers. 5753bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case PrintErrno: return "m"; 5763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 5773bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return NULL; 5783bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care} 5793bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5803bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 5813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care// Methods on LengthModifier. 5823bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 5833bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 5843bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Careconst char *LengthModifier::toString() const { 5853bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (kind) { 5863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsChar: 5873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "hh"; 5883bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsShort: 5893bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "h"; 5903bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsLong: // or AsWideChar 5913bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "l"; 5923bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsLongLong: 5933bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "ll"; 5943bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsIntMax: 5953bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "j"; 5963bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsSizeT: 5973bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "z"; 5983bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsPtrDiff: 5993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "t"; 6003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case AsLongDouble: 6013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return "L"; 6023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case None: 6033bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return ""; 6043bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 6053bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return NULL; 6063bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care} 6073bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 6083bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 6093bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care// Methods on OptionalAmount. 6103bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 6113bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 6123bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Carevoid OptionalAmount::toString(llvm::raw_ostream &os) const { 6133bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (hs) { 6143bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case Invalid: 6153bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case NotSpecified: 6163bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return; 6173bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case Arg: 6183bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (usesPositionalArg()) 6193bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << ".*" << getPositionalArgIndex() << "$"; 6203bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care else 6213bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << ".*"; 6223bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 6233bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case Constant: 6243bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << "." << amt; 6253bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 6263bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 6273bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care} 6283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 6293bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care//===----------------------------------------------------------------------===// 63033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek// Methods on FormatSpecifier. 63133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek//===----------------------------------------------------------------------===// 63233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 63333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted KremenekArgTypeResult FormatSpecifier::getArgType(ASTContext &Ctx) const { 63433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek if (!CS.consumesDataArgument()) 63533567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult::Invalid(); 6364e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 63733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek if (CS.isIntArg()) 6383bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (LM.getKind()) { 6393bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLongDouble: 64033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult::Invalid(); 6413bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::None: return Ctx.IntTy; 6423bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsChar: return Ctx.SignedCharTy; 6433bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsShort: return Ctx.ShortTy; 6443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLong: return Ctx.LongTy; 6453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLongLong: return Ctx.LongLongTy; 6463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsIntMax: 64733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: Return unknown for now. 64833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 6493bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsSizeT: return Ctx.getSizeType(); 6503bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsPtrDiff: return Ctx.getPointerDiffType(); 65133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek } 65233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 65333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek if (CS.isUIntArg()) 6543bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (LM.getKind()) { 6553bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLongDouble: 65633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult::Invalid(); 6573bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::None: return Ctx.UnsignedIntTy; 6583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsChar: return Ctx.UnsignedCharTy; 6593bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsShort: return Ctx.UnsignedShortTy; 6603bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLong: return Ctx.UnsignedLongTy; 6613bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsLongLong: return Ctx.UnsignedLongLongTy; 6623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsIntMax: 66333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: Return unknown for now. 66433567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 6653bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsSizeT: 66633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: How to get the corresponding unsigned 66733567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // version of size_t? 66833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 6693bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case LengthModifier::AsPtrDiff: 67033567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: How to get the corresponding unsigned 67133567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // version of ptrdiff_t? 67233567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek return ArgTypeResult(); 67333567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek } 6744e4b30ec62d78b24e6556fea2624855c193d0e3eTed Kremenek 675f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek if (CS.isDoubleArg()) { 6763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (LM.getKind() == LengthModifier::AsLongDouble) 677f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek return Ctx.LongDoubleTy; 678c9a89fec60a20eb3269caa95eca048d45ab215adTed Kremenek return Ctx.DoubleTy; 679f911eba72e6d7275e5cfdb79ab23fb2aa9cc01d0Ted Kremenek } 6807f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek 68187260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek switch (CS.getKind()) { 68287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case ConversionSpecifier::CStrArg: 6833bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return ArgTypeResult(LM.getKind() == LengthModifier::AsWideChar ? 6843bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care ArgTypeResult::WCStrTy : ArgTypeResult::CStrTy); 68587260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case ConversionSpecifier::UnicodeStrArg: 68687260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek // FIXME: This appears to be Mac OS X specific. 68787260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek return ArgTypeResult::WCStrTy; 68887260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek case ConversionSpecifier::CArg: 6897f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek return Ctx.WCharTy; 69013927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek case ConversionSpecifier::VoidPtrArg: 69113927a431dd733336cfd664bf0840747a71b0a43Ted Kremenek return ArgTypeResult::CPointerTy; 69287260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek default: 69387260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek break; 69487260c7eabf88eb2009ba2ba20150cd897483241Ted Kremenek } 6957f70dc85d5055c19c8003f43a59135de211ad1b9Ted Kremenek 69633567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek // FIXME: Handle other cases. 69740888ada6022cfd4ab2a7c07ab276639860ffc5aTed Kremenek return ArgTypeResult(); 69833567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek} 69933567d2feb3e52fac6e0b46d5b3d137fc8467fb0Ted Kremenek 7003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Carebool FormatSpecifier::fixType(QualType QT) { 7013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Handle strings first (char *, wchar_t *) 7023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) { 7033bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::CStrArg); 7043bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 705876e994957472eda4b40136d4e1d6e08e2be338fTom Care // Disable irrelevant flags 706876e994957472eda4b40136d4e1d6e08e2be338fTom Care HasAlternativeForm = 0; 707876e994957472eda4b40136d4e1d6e08e2be338fTom Care HasLeadingZeroes = 0; 708876e994957472eda4b40136d4e1d6e08e2be338fTom Care 7093bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Set the long length modifier for wide characters 7103bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (QT->getPointeeType()->isWideCharType()) 7113bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LM.setKind(LengthModifier::AsWideChar); 7123bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7133bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return true; 7143bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7153bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7163bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // We can only work with builtin types. 7173bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (!QT->isBuiltinType()) 7183bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return false; 7193bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7203bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Everything else should be a base type 7213bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care const BuiltinType *BT = QT->getAs<BuiltinType>(); 722876e994957472eda4b40136d4e1d6e08e2be338fTom Care 7233bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Set length modifier 7243bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care switch (BT->getKind()) { 7253bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care default: 726876e994957472eda4b40136d4e1d6e08e2be338fTom Care // The rest of the conversions are either optional or for non-builtin types 727876e994957472eda4b40136d4e1d6e08e2be338fTom Care LM.setKind(LengthModifier::None); 7283bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 729876e994957472eda4b40136d4e1d6e08e2be338fTom Care 7303bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::WChar: 7313bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::Long: 7323bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::ULong: 7333bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LM.setKind(LengthModifier::AsLong); 7343bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 7353bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7363bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::LongLong: 7373bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::ULongLong: 7383bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LM.setKind(LengthModifier::AsLongLong); 7393bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 7403bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7413bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care case BuiltinType::LongDouble: 7423bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care LM.setKind(LengthModifier::AsLongDouble); 7433bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care break; 7443bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7453bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7463bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Set conversion specifier and disable any flags which do not apply to it. 7473bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (QT->isAnyCharacterType()) { 7483bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::IntAsCharArg); 7493bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care Precision.setHowSpecified(OptionalAmount::NotSpecified); 7503bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasAlternativeForm = 0; 7513bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasLeadingZeroes = 0; 7523bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7533bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Test for Floating type first as LongDouble can pass isUnsignedIntegerType 7543bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care else if (QT->isFloatingType()) { 7553bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::fArg); 7563bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7573bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care else if (QT->isPointerType()) { 7583bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::VoidPtrArg); 7593bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care Precision.setHowSpecified(OptionalAmount::NotSpecified); 7603bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasAlternativeForm = 0; 7613bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasLeadingZeroes = 0; 7623bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7633bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care else if (QT->isSignedIntegerType()) { 7643bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::dArg); 7653bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasAlternativeForm = 0; 7663bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 767c8c4b4088cf0b3afeda425b25fa7c77d3873b12cDouglas Gregor else if (QT->isUnsignedIntegerType()) { 7683bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care CS.setKind(ConversionSpecifier::uArg); 7693bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care HasAlternativeForm = 0; 7703bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7713bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care else { 7723bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return false; 7733bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7743bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7753bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care return true; 7763bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care} 7773bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7783bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Carevoid FormatSpecifier::toString(llvm::raw_ostream &os) const { 7793bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Whilst some features have no defined order, we are using the order 7803bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // appearing in the C99 standard (ISO/IEC 9899:1999 (E) �7.19.6.1) 7813bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << "%"; 7823bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7833bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Positional args 7843bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (usesPositionalArg()) { 7853bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << getPositionalArgIndex() << "$"; 7863bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care } 7873bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7883bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Conversion flags 7893bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (IsLeftJustified) os << "-"; 7903bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (HasPlusPrefix) os << "+"; 7913bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (HasSpacePrefix) os << " "; 7923bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (HasAlternativeForm) os << "#"; 7933bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care if (HasLeadingZeroes) os << "0"; 7943bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care 7953bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Minimum field width 7963bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care FieldWidth.toString(os); 7973bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Precision 7983bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care Precision.toString(os); 7993bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Length modifier 8003bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << LM.toString(); 8013bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care // Conversion specifier 8023bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care os << CS.toString(); 8033bfc5f49e0e37e235bb0d33bcbcb36af9d1f84abTom Care} 804