FormatString.h revision 6ca4a9ae99d65948e578d3e7d1f58ab6a947d2d7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file defines APIs for analyzing the format strings of printf, fscanf, 11e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// and friends. 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The structure of format strings for fprintf are described in C99 7.19.6.1. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// The structure of format strings for fscanf are described in C99 7.19.6.2. 16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// 17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch//===----------------------------------------------------------------------===// 18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef LLVM_CLANG_FORMAT_H 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define LLVM_CLANG_FORMAT_H 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 22e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "clang/AST/CanonicalType.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace clang { 256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)/// Common components of both fprintf and fscanf format strings. 2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)namespace analyze_format_string { 29c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch/// Class representing optional flags with location and representation 31e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch/// information. 32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochclass OptionalFlag { 33e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochpublic: 34e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch OptionalFlag(const char *Representation) 35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch : representation(Representation), flag(false) {} 36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool isSet() { return flag; } 37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void set() { flag = true; } 38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void clear() { flag = false; } 39e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void setPosition(const char *position) { 40e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch assert(position); 41e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch this->position = position; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *getPosition() const { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(position); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return position; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const char *toString() const { return representation; } 48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Overloaded operators for bool like qualities 50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch operator bool() const { return flag; } 51e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch OptionalFlag& operator=(const bool &rhs) { 52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch flag = rhs; 53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return *this; // Return a reference to myself. 54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochprivate: 56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const char *representation; 57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const char *position; 58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool flag; 59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}; 60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch/// Represents the length modifier in a format string in scanf/printf. 62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochclass LengthModifier { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum Kind { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) None, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsChar, // 'hh' 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsShort, // 'h' 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsLong, // 'l' 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsLongLong, // 'll', 'q' (BSD, deprecated) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsIntMax, // 'j' 71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AsSizeT, // 'z' 72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AsPtrDiff, // 't' 73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AsLongDouble, // 'L' 74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) AsWideChar = AsLong // for '%ls', only makes sense for printf 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 77a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch LengthModifier() 78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : Position(0), kind(None) {} 79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch LengthModifier(const char *pos, Kind k) 80a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : Position(pos), kind(k) {} 81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const char *getStart() const { 83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return Position; 84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch unsigned getLength() const { 87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch switch (kind) { 88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) default: 89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return 1; 90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case AsLongLong: 91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch case AsChar: 92c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return 2; 93a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch case None: 94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return 0; 95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch Kind getKind() const { return kind; } 99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch void setKind(Kind k) { kind = k; } 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const char *toString() const; 102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 103a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochprivate: 104a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const char *Position; 105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch Kind kind; 106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}; 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochclass ConversionSpecifier { 109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochpublic: 110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch enum Kind { 111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch InvalidSpecifier = 0, 112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // C99 conversion specifiers. 113e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch cArg, 114e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch dArg, 115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch iArg, 116e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch IntArgBeg = cArg, IntArgEnd = iArg, 117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch oArg, 119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch uArg, 120e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch xArg, 121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch XArg, 122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch UIntArgBeg = oArg, UIntArgEnd = XArg, 123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch fArg, 125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch FArg, 126e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch eArg, 127a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch EArg, 128a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch gArg, 129a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch GArg, 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) aArg, 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) AArg, 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DoubleArgBeg = fArg, DoubleArgEnd = AArg, 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) sArg, 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) pArg, 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) nArg, 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PercentArg, 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CArg, 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) SArg, 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // ** Printf-specific ** 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Objective-C specific specifiers. 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ObjCObjArg, // '@' 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg, 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // GlibC specific specifiers. 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PrintErrno, // 'm' 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno, 151a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // ** Scanf-specific ** 153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ScanListArg, // '[' 154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg 155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch }; 1565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ConversionSpecifier(bool isPrintf) 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {} 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ConversionSpecifier(bool isPrintf, const char *pos, Kind k) 161a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {} 162a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 163a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const char *getStart() const { 164a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return Position; 165a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 166a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 167a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch StringRef getCharacters() const { 168a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return StringRef(getStart(), getLength()); 169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 170a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 171a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool consumesDataArgument() const { 172a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch switch (kind) { 173a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch case PrintErrno: 174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch assert(IsPrintf); 175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch case PercentArg: 176a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return false; 177a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch default: 178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return true; 179a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 181a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 182a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch Kind getKind() const { return kind; } 183a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch void setKind(Kind k) { kind = k; } 184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch unsigned getLength() const { 185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return EndScanList ? EndScanList - Position : 1; 186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const char *toString() const; 189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 190a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool isPrintfKind() const { return IsPrintf; } 191a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 192a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochprotected: 193a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool IsPrintf; 194a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const char *Position; 195a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const char *EndScanList; 196a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch Kind kind; 197a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}; 198a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 199a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochclass ArgTypeResult { 200a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochpublic: 201a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, 202a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch AnyCharTy, CStrTy, WCStrTy, WIntTy }; 203a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochprivate: 204a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const Kind K; 205a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch QualType T; 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ArgTypeResult(bool) : K(InvalidTy) {} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ArgTypeResult(Kind k = UnknownTy) : K(k) {} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ArgTypeResult(QualType t) : K(SpecificTy), T(t) {} 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ArgTypeResult(CanQualType t) : K(SpecificTy), T(t) {} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static ArgTypeResult Invalid() { return ArgTypeResult(true); } 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isValid() const { return K != InvalidTy; } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const QualType *getSpecificType() const { 217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return K == SpecificTy ? &T : 0; 218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool matchesType(ASTContext &C, QualType argTy) const; 221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool matchesAnyObjCObjectRef() const { return K == ObjCPointerTy; } 223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch QualType getRepresentativeType(ASTContext &C) const; 225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OptionalAmount { 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)public: 229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch enum HowSpecified { NotSpecified, Constant, Arg, Invalid }; 230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 231a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch OptionalAmount(HowSpecified howSpecified, 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unsigned amount, 233a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const char *amountStart, 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) unsigned amountLength, 235a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool usesPositionalArg) 236a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : start(amountStart), length(amountLength), hs(howSpecified), amt(amount), 237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {} 238a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 239a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch OptionalAmount(bool valid = true) 240c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0), 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) UsesPositionalArg(0), UsesDotPrefix(0) {} 242c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 243c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool isInvalid() const { 244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return hs == Invalid; 245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 246c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 247c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch HowSpecified getHowSpecified() const { return hs; } 248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch void setHowSpecified(HowSpecified h) { hs = h; } 249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool hasDataArgument() const { return hs == Arg; } 251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch unsigned getArgIndex() const { 253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch assert(hasDataArgument()); 254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return amt; 255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch unsigned getConstantAmount() const { 258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch assert(hs == Constant); 259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return amt; 260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch const char *getStart() const { 263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // We include the . character if it is given. 264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return start - UsesDotPrefix; 265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch unsigned getConstantLength() const { 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) assert(hs == Constant); 269e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return length + UsesDotPrefix; 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 271e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 272e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ArgTypeResult getArgType(ASTContext &Ctx) const; 273e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 274e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch void toString(raw_ostream &os) const; 275e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 276e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool usesPositionalArg() const { return (bool) UsesPositionalArg; } 277e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch unsigned getPositionalArgIndex() const { 278e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch assert(hasDataArgument()); 279e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return amt + 1; 280e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 281e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 282e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch bool usesDotPrefix() const { return UsesDotPrefix; } 283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void setUsesDotPrefix() { UsesDotPrefix = true; } 284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)private: 286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char *start; 287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) unsigned length; 288e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch HowSpecified hs; 289e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch unsigned amt; 29046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool UsesPositionalArg : 1; 29146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool UsesDotPrefix; 29246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class FormatSpecifier { 29646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)protected: 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LengthModifier LM; 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OptionalAmount FieldWidth; 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ConversionSpecifier CS; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// Positional arguments, an IEEE extension: 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /// IEEE Std 1003.1, 2004 Edition 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool UsesPositionalArg; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned argIndex; 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FormatSpecifier(bool isPrintf) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {} 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void setLengthModifier(LengthModifier lm) { 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LM = lm; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void setUsesPositionalArg() { UsesPositionalArg = true; } 3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void setArgIndex(unsigned i) { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) argIndex = i; 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned getArgIndex() const { 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return argIndex; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned getPositionalArgIndex() const { 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return argIndex + 1; 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const LengthModifier &getLengthModifier() const { 328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return LM; 329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const OptionalAmount &getFieldWidth() const { 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return FieldWidth; 333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void setFieldWidth(const OptionalAmount &Amt) { 336cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FieldWidth = Amt; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool usesPositionalArg() const { return UsesPositionalArg; } 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool hasValidLengthModifier() const; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // end analyze_format_string namespace 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// Pieces specific to fprintf format strings. 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace analyze_printf { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PrintfConversionSpecifier : 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public analyze_format_string::ConversionSpecifier { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)public: 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintfConversionSpecifier() 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ConversionSpecifier(true, 0, InvalidSpecifier) {} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrintfConversionSpecifier(const char *pos, Kind k) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ConversionSpecifier(true, pos, k) {} 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; } 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; } 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool isDoubleArg() const { return kind >= DoubleArgBeg && 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kind <= DoubleArgBeg; } 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned getLength() const { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Conversion specifiers currently only are represented by 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // single characters, but we be flexible. 368c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return 1; 369c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 370c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool classof(const analyze_format_string::ConversionSpecifier *CS) { 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CS->isPrintfKind(); 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using analyze_format_string::ArgTypeResult; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using analyze_format_string::LengthModifier; 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using analyze_format_string::OptionalAmount; 37946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using analyze_format_string::OptionalFlag; 38046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 38146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class PrintfSpecifier : public analyze_format_string::FormatSpecifier { 382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OptionalFlag HasThousandsGrouping; // ''', POSIX extension. 383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OptionalFlag IsLeftJustified; // '-' 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OptionalFlag HasPlusPrefix; // '+' 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OptionalFlag HasSpacePrefix; // ' ' 386c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch OptionalFlag HasAlternativeForm; // '#' 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OptionalFlag HasLeadingZeroes; // '0' 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OptionalAmount Precision; 389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)public: 390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PrintfSpecifier() : 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FormatSpecifier(/* isPrintf = */ true), 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasThousandsGrouping("'"), IsLeftJustified("-"), HasPlusPrefix("+"), 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasSpacePrefix(" "), HasAlternativeForm("#"), HasLeadingZeroes("0") {} 394cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 395cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) static PrintfSpecifier Parse(const char *beg, const char *end); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Methods for incrementally constructing the PrintfSpecifier. 398c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch void setConversionSpecifier(const PrintfConversionSpecifier &cs) { 399c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CS = cs; 400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch void setHasThousandsGrouping(const char *position) { 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasThousandsGrouping = true; 403f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) HasThousandsGrouping.setPosition(position); 404f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void setIsLeftJustified(const char *position) { 406f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) IsLeftJustified = true; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsLeftJustified.setPosition(position); 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void setHasPlusPrefix(const char *position) { 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasPlusPrefix = true; 411cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) HasPlusPrefix.setPosition(position); 412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 413cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void setHasSpacePrefix(const char *position) { 414010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) HasSpacePrefix = true; 415010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) HasSpacePrefix.setPosition(position); 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void setHasAlternativeForm(const char *position) { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasAlternativeForm = true; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasAlternativeForm.setPosition(position); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void setHasLeadingZeros(const char *position) { 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasLeadingZeroes = true; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HasLeadingZeroes.setPosition(position); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void setUsesPositionalArg() { UsesPositionalArg = true; } 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Methods for querying the format specifier. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const PrintfConversionSpecifier &getConversionSpecifier() const { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return cast<PrintfConversionSpecifier>(CS); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void setPrecision(const OptionalAmount &Amt) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Precision = Amt; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Precision.setUsesDotPrefix(); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const OptionalAmount &getPrecision() const { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return Precision; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool consumesDataArgument() const { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return getConversionSpecifier().consumesDataArgument(); 44458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// \brief Returns the builtin type that a data argument 447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) /// paired with this format specifier should have. This method 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// will return null if the format specifier does not have 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// a matching data argument or the matching argument matches 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /// more than one type. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ArgTypeResult getArgType(ASTContext &Ctx) const; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 453 const OptionalFlag &hasThousandsGrouping() const { 454 return HasThousandsGrouping; 455 } 456 const OptionalFlag &isLeftJustified() const { return IsLeftJustified; } 457 const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; } 458 const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; } 459 const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; } 460 const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; } 461 bool usesPositionalArg() const { return UsesPositionalArg; } 462 463 /// Changes the specifier and length according to a QualType, retaining any 464 /// flags or options. Returns true on success, or false when a conversion 465 /// was not successful. 466 bool fixType(QualType QT, const LangOptions &LangOpt); 467 468 void toString(raw_ostream &os) const; 469 470 // Validation methods - to check if any element results in undefined behavior 471 bool hasValidPlusPrefix() const; 472 bool hasValidAlternativeForm() const; 473 bool hasValidLeadingZeros() const; 474 bool hasValidSpacePrefix() const; 475 bool hasValidLeftJustified() const; 476 bool hasValidThousandsGroupingPrefix() const; 477 478 bool hasValidPrecision() const; 479 bool hasValidFieldWidth() const; 480}; 481} // end analyze_printf namespace 482 483//===----------------------------------------------------------------------===// 484/// Pieces specific to fscanf format strings. 485 486namespace analyze_scanf { 487 488class ScanfConversionSpecifier : 489 public analyze_format_string::ConversionSpecifier { 490public: 491 ScanfConversionSpecifier() 492 : ConversionSpecifier(false, 0, InvalidSpecifier) {} 493 494 ScanfConversionSpecifier(const char *pos, Kind k) 495 : ConversionSpecifier(false, pos, k) {} 496 497 void setEndScanList(const char *pos) { EndScanList = pos; } 498 499 static bool classof(const analyze_format_string::ConversionSpecifier *CS) { 500 return !CS->isPrintfKind(); 501 } 502}; 503 504using analyze_format_string::LengthModifier; 505using analyze_format_string::OptionalAmount; 506using analyze_format_string::OptionalFlag; 507 508class ScanfSpecifier : public analyze_format_string::FormatSpecifier { 509 OptionalFlag SuppressAssignment; // '*' 510public: 511 ScanfSpecifier() : 512 FormatSpecifier(/* isPrintf = */ false), 513 SuppressAssignment("*") {} 514 515 void setSuppressAssignment(const char *position) { 516 SuppressAssignment = true; 517 SuppressAssignment.setPosition(position); 518 } 519 520 const OptionalFlag &getSuppressAssignment() const { 521 return SuppressAssignment; 522 } 523 524 void setConversionSpecifier(const ScanfConversionSpecifier &cs) { 525 CS = cs; 526 } 527 528 const ScanfConversionSpecifier &getConversionSpecifier() const { 529 return cast<ScanfConversionSpecifier>(CS); 530 } 531 532 bool consumesDataArgument() const { 533 return CS.consumesDataArgument() && !SuppressAssignment; 534 } 535 536 static ScanfSpecifier Parse(const char *beg, const char *end); 537}; 538 539} // end analyze_scanf namespace 540 541//===----------------------------------------------------------------------===// 542// Parsing and processing of format strings (both fprintf and fscanf). 543 544namespace analyze_format_string { 545 546enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 }; 547 548class FormatStringHandler { 549public: 550 FormatStringHandler() {} 551 virtual ~FormatStringHandler(); 552 553 virtual void HandleNullChar(const char *nullCharacter) {} 554 555 virtual void HandleInvalidPosition(const char *startPos, unsigned posLen, 556 PositionContext p) {} 557 558 virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {} 559 560 virtual void HandleIncompleteSpecifier(const char *startSpecifier, 561 unsigned specifierLen) {} 562 563 // Printf-specific handlers. 564 565 virtual bool HandleInvalidPrintfConversionSpecifier( 566 const analyze_printf::PrintfSpecifier &FS, 567 const char *startSpecifier, 568 unsigned specifierLen) { 569 return true; 570 } 571 572 virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS, 573 const char *startSpecifier, 574 unsigned specifierLen) { 575 return true; 576 } 577 578 // Scanf-specific handlers. 579 580 virtual bool HandleInvalidScanfConversionSpecifier( 581 const analyze_scanf::ScanfSpecifier &FS, 582 const char *startSpecifier, 583 unsigned specifierLen) { 584 return true; 585 } 586 587 virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS, 588 const char *startSpecifier, 589 unsigned specifierLen) { 590 return true; 591 } 592 593 virtual void HandleIncompleteScanList(const char *start, const char *end) {} 594}; 595 596bool ParsePrintfString(FormatStringHandler &H, 597 const char *beg, const char *end); 598 599bool ParseScanfString(FormatStringHandler &H, 600 const char *beg, const char *end); 601 602} // end analyze_format_string namespace 603} // end clang namespace 604#endif 605