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