1826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//= FormatString.h - Analysis of printf/fprintf format strings --*- C++ -*-===//
2826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//
3826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//                     The LLVM Compiler Infrastructure
4826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//
5826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// This file is distributed under the University of Illinois Open Source
6826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// License. See LICENSE.TXT for details.
7826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//
8826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//===----------------------------------------------------------------------===//
9826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//
10826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// This file defines APIs for analyzing the format strings of printf, fscanf,
11826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// and friends.
12826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//
13826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// The structure of format strings for fprintf are described in C99 7.19.6.1.
14826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//
15826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// The structure of format strings for fscanf are described in C99 7.19.6.2.
16826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//
17826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//===----------------------------------------------------------------------===//
18826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
19826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek#ifndef LLVM_CLANG_FORMAT_H
20826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek#define LLVM_CLANG_FORMAT_H
21826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
22826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek#include "clang/AST/CanonicalType.h"
23826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
24826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremeneknamespace clang {
25826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
26bbb6bb4952b77e57b842b4d3096848123ae690e7Jordan Roseclass TargetInfo;
27bbb6bb4952b77e57b842b4d3096848123ae690e7Jordan Rose
28826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//===----------------------------------------------------------------------===//
29826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek/// Common components of both fprintf and fscanf format strings.
30826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremeneknamespace analyze_format_string {
31826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
32826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek/// Class representing optional flags with location and representation
33826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek/// information.
34826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekclass OptionalFlag {
35826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
36826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalFlag(const char *Representation)
37826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      : representation(Representation), flag(false) {}
38826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool isSet() { return flag; }
39826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void set() { flag = true; }
40826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void clear() { flag = false; }
41826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setPosition(const char *position) {
42826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    assert(position);
43826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    this->position = position;
44826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
45826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const char *getPosition() const {
46826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    assert(position);
47826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return position;
48826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
49826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const char *toString() const { return representation; }
50826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
51826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  // Overloaded operators for bool like qualities
527247c88d1e41514a41085f83ebf03dd5220e054aDavid Blaikie  LLVM_EXPLICIT operator bool() const { return flag; }
53826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalFlag& operator=(const bool &rhs) {
54826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    flag = rhs;
55826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return *this;  // Return a reference to myself.
56826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
57826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekprivate:
58826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const char *representation;
59826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const char *position;
60826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool flag;
61826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek};
62826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
63826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek/// Represents the length modifier in a format string in scanf/printf.
64826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekclass LengthModifier {
65826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
66826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  enum Kind {
67826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    None,
68826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    AsChar,       // 'hh'
69826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    AsShort,      // 'h'
70826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    AsLong,       // 'l'
7132addd519c6699000ff79c387a1c87f0ab7c3698Hans Wennborg    AsLongLong,   // 'll'
72a76879eb4c75dbd9ec671558f0b8b79a28d4d747Hans Wennborg    AsQuad,       // 'q' (BSD, deprecated, for 64-bit integer types)
73826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    AsIntMax,     // 'j'
74826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    AsSizeT,      // 'z'
75826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    AsPtrDiff,    // 't'
76826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    AsLongDouble, // 'L'
7737969b7e14d6a4dfd934ef6d3738cc90b832ec1dHans Wennborg    AsAllocate,   // for '%as', GNU extension to C90 scanf
7837969b7e14d6a4dfd934ef6d3738cc90b832ec1dHans Wennborg    AsMAllocate,  // for '%ms', GNU extension to scanf
79826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    AsWideChar = AsLong // for '%ls', only makes sense for printf
80826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  };
81826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
82826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  LengthModifier()
83826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    : Position(0), kind(None) {}
84826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  LengthModifier(const char *pos, Kind k)
85826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    : Position(pos), kind(k) {}
86826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
87826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const char *getStart() const {
88826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return Position;
89826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
90826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
91826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned getLength() const {
92826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    switch (kind) {
93826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      default:
94826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek        return 1;
95826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      case AsLongLong:
96826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      case AsChar:
97826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek        return 2;
98826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      case None:
99826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek        return 0;
100826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    }
101826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
102826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
103826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  Kind getKind() const { return kind; }
104826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setKind(Kind k) { kind = k; }
105826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
106826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const char *toString() const;
107826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
108826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekprivate:
109826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const char *Position;
110826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  Kind kind;
111826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek};
112ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1136ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenekclass ConversionSpecifier {
1146ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenekpublic:
1156ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  enum Kind {
1166ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    InvalidSpecifier = 0,
1176ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek      // C99 conversion specifiers.
1186ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    cArg,
1196ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    dArg,
120275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose    DArg, // Apple extension
1216ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    iArg,
1228be066e6733364cd34f25c4f7b7344f72aa23369Jordan Rose    IntArgBeg = dArg, IntArgEnd = iArg,
123ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1246ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    oArg,
125275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose    OArg, // Apple extension
1266ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    uArg,
127275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose    UArg, // Apple extension
1286ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    xArg,
1296ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    XArg,
1306ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    UIntArgBeg = oArg, UIntArgEnd = XArg,
131ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1326ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    fArg,
1336ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    FArg,
1346ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    eArg,
1356ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    EArg,
1366ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    gArg,
1376ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    GArg,
1386ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    aArg,
1396ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    AArg,
1406ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    DoubleArgBeg = fArg, DoubleArgEnd = AArg,
141ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1426ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    sArg,
1436ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    pArg,
1446ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    nArg,
1456ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    PercentArg,
1466ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    CArg,
1476ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    SArg,
148ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1496ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    // ** Printf-specific **
150ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1516ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    // Objective-C specific specifiers.
1526ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    ObjCObjArg,  // '@'
1536ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg,
154ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1556ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    // GlibC specific specifiers.
1566ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    PrintErrno,   // 'm'
157ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
158cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    PrintfConvBeg = ObjCObjArg, PrintfConvEnd = PrintErrno,
159ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
160ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie    // ** Scanf-specific **
161cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    ScanListArg, // '['
162cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    ScanfConvBeg = ScanListArg, ScanfConvEnd = ScanListArg
1636ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  };
164ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
165670941c28c0683ecc251dafdf093a71629625dc9Jordan Rose  ConversionSpecifier(bool isPrintf = true)
166cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    : IsPrintf(isPrintf), Position(0), EndScanList(0), kind(InvalidSpecifier) {}
167ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1686ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  ConversionSpecifier(bool isPrintf, const char *pos, Kind k)
169cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    : IsPrintf(isPrintf), Position(pos), EndScanList(0), kind(k) {}
170ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1716ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  const char *getStart() const {
1726ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    return Position;
1736ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  }
174ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
175686775deca8b8685eb90801495880e3abdd844c2Chris Lattner  StringRef getCharacters() const {
176686775deca8b8685eb90801495880e3abdd844c2Chris Lattner    return StringRef(getStart(), getLength());
1776ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  }
178ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
179cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek  bool consumesDataArgument() const {
180cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    switch (kind) {
181cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek      case PrintErrno:
182cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek        assert(IsPrintf);
183d39d23e610c2a7815515d60c5a538d65d05e8bdcRichard Smith        return false;
184cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek      case PercentArg:
185cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek        return false;
186cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek      default:
187cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek        return true;
188cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    }
189cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek  }
190ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1916ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  Kind getKind() const { return kind; }
1926ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  void setKind(Kind k) { kind = k; }
1936ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  unsigned getLength() const {
194cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    return EndScanList ? EndScanList - Position : 1;
1956ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  }
196ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
1978be066e6733364cd34f25c4f7b7344f72aa23369Jordan Rose  bool isIntArg() const { return kind >= IntArgBeg && kind <= IntArgEnd; }
1986fcd932dfd6835f70cc00d6f7c6789793f6d7b66Hans Wennborg  bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; }
1998be066e6733364cd34f25c4f7b7344f72aa23369Jordan Rose  bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; }
2006ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  const char *toString() const;
201ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
2026ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  bool isPrintfKind() const { return IsPrintf; }
203670941c28c0683ecc251dafdf093a71629625dc9Jordan Rose
204dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie  Optional<ConversionSpecifier> getStandardSpecifier() const;
2056ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek
2066ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenekprotected:
2076ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  bool IsPrintf;
2086ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  const char *Position;
209cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek  const char *EndScanList;
2106ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  Kind kind;
2116ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek};
212826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
213f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborgclass ArgType {
214826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
215826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy,
216f4f0c6095d1f481b94c6821c65e3bf1c9df42af7Hans Wennborg              AnyCharTy, CStrTy, WCStrTy, WIntTy };
217826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekprivate:
218826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const Kind K;
219826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  QualType T;
220a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg  const char *Name;
22158e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg  bool Ptr;
222826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
22358e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg  ArgType(Kind k = UnknownTy, const char *n = 0) : K(k), Name(n), Ptr(false) {}
22458e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg  ArgType(QualType t, const char *n = 0)
22558e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg      : K(SpecificTy), T(t), Name(n), Ptr(false) {}
22658e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg  ArgType(CanQualType t) : K(SpecificTy), T(t), Name(0), Ptr(false) {}
227826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
228f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg  static ArgType Invalid() { return ArgType(InvalidTy); }
229826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool isValid() const { return K != InvalidTy; }
230826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
23158e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg  /// Create an ArgType which corresponds to the type pointer to A.
23258e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg  static ArgType PtrTo(const ArgType& A) {
23358e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg    assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown");
23458e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg    ArgType Res = A;
23558e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg    Res.Ptr = true;
23658e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg    return Res;
23758e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg  }
23858e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg
239826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool matchesType(ASTContext &C, QualType argTy) const;
240826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
241826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  QualType getRepresentativeType(ASTContext &C) const;
242a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg
243a792aff1c7de253b89c473fdb7eef4a5bba83aecHans Wennborg  std::string getRepresentativeTypeName(ASTContext &C) const;
244826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek};
245826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
246826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekclass OptionalAmount {
247826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
248826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  enum HowSpecified { NotSpecified, Constant, Arg, Invalid };
249826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
250826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalAmount(HowSpecified howSpecified,
251826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                 unsigned amount,
252826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                 const char *amountStart,
253826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                 unsigned amountLength,
254826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                 bool usesPositionalArg)
255826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  : start(amountStart), length(amountLength), hs(howSpecified), amt(amount),
256826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {}
257826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
258826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalAmount(bool valid = true)
259826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0),
260826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  UsesPositionalArg(0), UsesDotPrefix(0) {}
261826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
262826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool isInvalid() const {
263826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return hs == Invalid;
264826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
265826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
266826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  HowSpecified getHowSpecified() const { return hs; }
267826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setHowSpecified(HowSpecified h) { hs = h; }
268826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
269826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool hasDataArgument() const { return hs == Arg; }
270826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
271826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned getArgIndex() const {
272826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    assert(hasDataArgument());
273826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return amt;
274826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
275826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
276826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned getConstantAmount() const {
277826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    assert(hs == Constant);
278826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return amt;
279826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
280826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
281826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const char *getStart() const {
282826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      // We include the . character if it is given.
283826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return start - UsesDotPrefix;
284826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
285826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
286826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned getConstantLength() const {
287826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    assert(hs == Constant);
288826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return length + UsesDotPrefix;
289826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
290826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
291f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg  ArgType getArgType(ASTContext &Ctx) const;
292826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
2938cc488fefb2fb04bc8d5398da29f0182f97934cfChris Lattner  void toString(raw_ostream &os) const;
294826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
295826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool usesPositionalArg() const { return (bool) UsesPositionalArg; }
296826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned getPositionalArgIndex() const {
297826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    assert(hasDataArgument());
298826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return amt + 1;
299826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
300826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
301826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool usesDotPrefix() const { return UsesDotPrefix; }
302826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setUsesDotPrefix() { UsesDotPrefix = true; }
303826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
304826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekprivate:
305826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const char *start;
306826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned length;
307826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  HowSpecified hs;
308826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned amt;
309826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool UsesPositionalArg : 1;
310826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool UsesDotPrefix;
311826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek};
312826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
313826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
314826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekclass FormatSpecifier {
315826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekprotected:
316826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  LengthModifier LM;
317826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalAmount FieldWidth;
318a412a499162c46211c10ad92045b9b5fd2298edeTed Kremenek  ConversionSpecifier CS;
319f85626453123f9691bcef13cff963f556e209c27Hans Wennborg  /// Positional arguments, an IEEE extension:
320f85626453123f9691bcef13cff963f556e209c27Hans Wennborg  ///  IEEE Std 1003.1, 2004 Edition
321f85626453123f9691bcef13cff963f556e209c27Hans Wennborg  ///  http://www.opengroup.org/onlinepubs/009695399/functions/printf.html
322826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool UsesPositionalArg;
323826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned argIndex;
324826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
325a412a499162c46211c10ad92045b9b5fd2298edeTed Kremenek  FormatSpecifier(bool isPrintf)
326a412a499162c46211c10ad92045b9b5fd2298edeTed Kremenek    : CS(isPrintf), UsesPositionalArg(false), argIndex(0) {}
327826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
328826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setLengthModifier(LengthModifier lm) {
329826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    LM = lm;
330826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
331826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
332826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setUsesPositionalArg() { UsesPositionalArg = true; }
333826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
334826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setArgIndex(unsigned i) {
335826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    argIndex = i;
336826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
337826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
338826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned getArgIndex() const {
339826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return argIndex;
340826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
341826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
342826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned getPositionalArgIndex() const {
343826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return argIndex + 1;
344826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
345826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
346826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const LengthModifier &getLengthModifier() const {
347826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return LM;
348826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
349826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
350826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const OptionalAmount &getFieldWidth() const {
351826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return FieldWidth;
352826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
353826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
354826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setFieldWidth(const OptionalAmount &Amt) {
355826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    FieldWidth = Amt;
356826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
357826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
358826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool usesPositionalArg() const { return UsesPositionalArg; }
359ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
360bbb6bb4952b77e57b842b4d3096848123ae690e7Jordan Rose  bool hasValidLengthModifier(const TargetInfo &Target) const;
36176517426dc8bf7734c07eefc35171a6bfdba1a2bHans Wennborg
36276517426dc8bf7734c07eefc35171a6bfdba1a2bHans Wennborg  bool hasStandardLengthModifier() const;
36376517426dc8bf7734c07eefc35171a6bfdba1a2bHans Wennborg
364dc84cd5efdd3430efb22546b4ac656aa0540b210David Blaikie  Optional<LengthModifier> getCorrectedLengthModifier() const;
365bbb6bb4952b77e57b842b4d3096848123ae690e7Jordan Rose
36676517426dc8bf7734c07eefc35171a6bfdba1a2bHans Wennborg  bool hasStandardConversionSpecifier(const LangOptions &LangOpt) const;
36776517426dc8bf7734c07eefc35171a6bfdba1a2bHans Wennborg
36876517426dc8bf7734c07eefc35171a6bfdba1a2bHans Wennborg  bool hasStandardLengthConversionCombination() const;
3694684778993c667246039b4664acbce59dc99440cHans Wennborg
3704684778993c667246039b4664acbce59dc99440cHans Wennborg  /// For a TypedefType QT, if it is a named integer type such as size_t,
3714684778993c667246039b4664acbce59dc99440cHans Wennborg  /// assign the appropriate value to LM and return true.
3724684778993c667246039b4664acbce59dc99440cHans Wennborg  static bool namedTypeToLengthModifier(QualType QT, LengthModifier &LM);
373826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek};
374826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
375826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek} // end analyze_format_string namespace
376826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
377826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//===----------------------------------------------------------------------===//
378826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek/// Pieces specific to fprintf format strings.
379826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
380826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremeneknamespace analyze_printf {
381826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
382ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikieclass PrintfConversionSpecifier :
3836ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  public analyze_format_string::ConversionSpecifier  {
384826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
3856ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  PrintfConversionSpecifier()
3866ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    : ConversionSpecifier(true, 0, InvalidSpecifier) {}
3872da5036adaef57395270ef2dd82358fc513d8616Ted Kremenek
3886ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  PrintfConversionSpecifier(const char *pos, Kind k)
3896ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    : ConversionSpecifier(true, pos, k) {}
390826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
391826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; }
392ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  bool isDoubleArg() const { return kind >= DoubleArgBeg &&
3934ee01ef7bd170b6f3f3f71882b407cd6408c5b1eHans Wennborg                                    kind <= DoubleArgEnd; }
394826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  unsigned getLength() const {
395826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      // Conversion specifiers currently only are represented by
396826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek      // single characters, but we be flexible.
397826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return 1;
398826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
399826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
4006ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
4016ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    return CS->isPrintfKind();
4026ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  }
403826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek};
404826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
405f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborgusing analyze_format_string::ArgType;
406826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing analyze_format_string::LengthModifier;
407826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing analyze_format_string::OptionalAmount;
408826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing analyze_format_string::OptionalFlag;
409826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
410826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekclass PrintfSpecifier : public analyze_format_string::FormatSpecifier {
411bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek  OptionalFlag HasThousandsGrouping; // ''', POSIX extension.
412826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalFlag IsLeftJustified; // '-'
413826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalFlag HasPlusPrefix; // '+'
414826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalFlag HasSpacePrefix; // ' '
415826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalFlag HasAlternativeForm; // '#'
416826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalFlag HasLeadingZeroes; // '0'
417826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalAmount Precision;
418826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
419826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  PrintfSpecifier() :
420a412a499162c46211c10ad92045b9b5fd2298edeTed Kremenek    FormatSpecifier(/* isPrintf = */ true),
421bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek    HasThousandsGrouping("'"), IsLeftJustified("-"), HasPlusPrefix("+"),
422bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek    HasSpacePrefix(" "), HasAlternativeForm("#"), HasLeadingZeroes("0") {}
423826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
424826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  static PrintfSpecifier Parse(const char *beg, const char *end);
425826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
426826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    // Methods for incrementally constructing the PrintfSpecifier.
4276ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  void setConversionSpecifier(const PrintfConversionSpecifier &cs) {
428826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    CS = cs;
429826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
430bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek  void setHasThousandsGrouping(const char *position) {
431bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek    HasThousandsGrouping = true;
432bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek    HasThousandsGrouping.setPosition(position);
433bd18d4584aae0ed6f7111ef5713784cf29fe663fTed Kremenek  }
434826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setIsLeftJustified(const char *position) {
435826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    IsLeftJustified = true;
436826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    IsLeftJustified.setPosition(position);
437826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
438826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setHasPlusPrefix(const char *position) {
439826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    HasPlusPrefix = true;
440826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    HasPlusPrefix.setPosition(position);
441826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
442826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setHasSpacePrefix(const char *position) {
443826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    HasSpacePrefix = true;
444826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    HasSpacePrefix.setPosition(position);
445826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
446826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setHasAlternativeForm(const char *position) {
447826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    HasAlternativeForm = true;
448826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    HasAlternativeForm.setPosition(position);
449826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
450826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setHasLeadingZeros(const char *position) {
451826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    HasLeadingZeroes = true;
452826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    HasLeadingZeroes.setPosition(position);
453826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
454826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setUsesPositionalArg() { UsesPositionalArg = true; }
455826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
456826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    // Methods for querying the format specifier.
457826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
4586ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  const PrintfConversionSpecifier &getConversionSpecifier() const {
4596ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    return cast<PrintfConversionSpecifier>(CS);
460826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
461826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
462826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setPrecision(const OptionalAmount &Amt) {
463826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    Precision = Amt;
464826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    Precision.setUsesDotPrefix();
465826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
466826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
467826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const OptionalAmount &getPrecision() const {
468826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return Precision;
469826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
470ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
471baa400654bd6f8396f9a07188445ae7955b060a3Ted Kremenek  bool consumesDataArgument() const {
4726ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek    return getConversionSpecifier().consumesDataArgument();
473baa400654bd6f8396f9a07188445ae7955b060a3Ted Kremenek  }
474826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
47596827eb52405a71c65c200949f3e644368e86454Michael J. Spencer  /// \brief Returns the builtin type that a data argument
476baa400654bd6f8396f9a07188445ae7955b060a3Ted Kremenek  /// paired with this format specifier should have.  This method
47796827eb52405a71c65c200949f3e644368e86454Michael J. Spencer  /// will return null if the format specifier does not have
478baa400654bd6f8396f9a07188445ae7955b060a3Ted Kremenek  /// a matching data argument or the matching argument matches
479baa400654bd6f8396f9a07188445ae7955b060a3Ted Kremenek  /// more than one type.
480f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborg  ArgType getArgType(ASTContext &Ctx, bool IsObjCLiteral) const;
481826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
482ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  const OptionalFlag &hasThousandsGrouping() const {
48365197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek      return HasThousandsGrouping;
48465197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  }
485826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const OptionalFlag &isLeftJustified() const { return IsLeftJustified; }
486826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; }
487826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; }
488826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; }
489826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; }
490826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool usesPositionalArg() const { return UsesPositionalArg; }
491826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
492be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg  /// Changes the specifier and length according to a QualType, retaining any
493be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg  /// flags or options. Returns true on success, or false when a conversion
494be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg  /// was not successful.
495be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg  bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx,
496be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg               bool IsObjCLiteral);
497826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
4988cc488fefb2fb04bc8d5398da29f0182f97934cfChris Lattner  void toString(raw_ostream &os) const;
499826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
500ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  // Validation methods - to check if any element results in undefined behavior
501826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool hasValidPlusPrefix() const;
502826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool hasValidAlternativeForm() const;
503826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool hasValidLeadingZeros() const;
504826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool hasValidSpacePrefix() const;
505826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool hasValidLeftJustified() const;
50665197b4b0c55bb74af0450230d61ee9461223721Ted Kremenek  bool hasValidThousandsGroupingPrefix() const;
507826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
508826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool hasValidPrecision() const;
509826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool hasValidFieldWidth() const;
510826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek};
511826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek}  // end analyze_printf namespace
512826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
513826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//===----------------------------------------------------------------------===//
514826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek/// Pieces specific to fscanf format strings.
515826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
516826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremeneknamespace analyze_scanf {
517826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
518cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenekclass ScanfConversionSpecifier :
519cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    public analyze_format_string::ConversionSpecifier  {
520826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
5216ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  ScanfConversionSpecifier()
522cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    : ConversionSpecifier(false, 0, InvalidSpecifier) {}
523826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
5246ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  ScanfConversionSpecifier(const char *pos, Kind k)
525cfdcd3066521ee0fa9f303f3863c726943db37e5Ted Kremenek    : ConversionSpecifier(false, pos, k) {}
526826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
527826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setEndScanList(const char *pos) { EndScanList = pos; }
528ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
529a412a499162c46211c10ad92045b9b5fd2298edeTed Kremenek  static bool classof(const analyze_format_string::ConversionSpecifier *CS) {
530a412a499162c46211c10ad92045b9b5fd2298edeTed Kremenek    return !CS->isPrintfKind();
531ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie  }
532826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek};
533826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
534f3749f4168c5cee59627a681ca4ca6e4116d0761Hans Wennborgusing analyze_format_string::ArgType;
535826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing analyze_format_string::LengthModifier;
536826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing analyze_format_string::OptionalAmount;
537826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekusing analyze_format_string::OptionalFlag;
538826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
539826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekclass ScanfSpecifier : public analyze_format_string::FormatSpecifier {
540826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  OptionalFlag SuppressAssignment; // '*'
541826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
542a412a499162c46211c10ad92045b9b5fd2298edeTed Kremenek  ScanfSpecifier() :
543a412a499162c46211c10ad92045b9b5fd2298edeTed Kremenek    FormatSpecifier(/* isPrintf = */ false),
544a412a499162c46211c10ad92045b9b5fd2298edeTed Kremenek    SuppressAssignment("*") {}
545826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
546826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  void setSuppressAssignment(const char *position) {
547826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    SuppressAssignment = true;
548826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    SuppressAssignment.setPosition(position);
549826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
550826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
551826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  const OptionalFlag &getSuppressAssignment() const {
552826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return SuppressAssignment;
553826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
554826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
5556ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  void setConversionSpecifier(const ScanfConversionSpecifier &cs) {
556826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    CS = cs;
557826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
558826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
5596ecb950c65329f8d6ce9ad0514632df35a5ab61fTed Kremenek  const ScanfConversionSpecifier &getConversionSpecifier() const {
560a412a499162c46211c10ad92045b9b5fd2298edeTed Kremenek    return cast<ScanfConversionSpecifier>(CS);
561826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
562ba243b59a1074e0962f6abfa3bb9aa984eac1245David Blaikie
563826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  bool consumesDataArgument() const {
564826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return CS.consumesDataArgument() && !SuppressAssignment;
565826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
566826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
56758e1e54476d610d6c33ef483f216ed8a1282d35cHans Wennborg  ArgType getArgType(ASTContext &Ctx) const;
5686fcd932dfd6835f70cc00d6f7c6789793f6d7b66Hans Wennborg
569be6126a2a784e1446460b8d15c2b26f880c871fcHans Wennborg  bool fixType(QualType QT, const LangOptions &LangOpt, ASTContext &Ctx);
5706fcd932dfd6835f70cc00d6f7c6789793f6d7b66Hans Wennborg
5716fcd932dfd6835f70cc00d6f7c6789793f6d7b66Hans Wennborg  void toString(raw_ostream &os) const;
5726fcd932dfd6835f70cc00d6f7c6789793f6d7b66Hans Wennborg
573826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  static ScanfSpecifier Parse(const char *beg, const char *end);
574826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek};
575826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
576826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek} // end analyze_scanf namespace
577826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
578826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek//===----------------------------------------------------------------------===//
579826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek// Parsing and processing of format strings (both fprintf and fscanf).
580826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
581826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremeneknamespace analyze_format_string {
582826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
583826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekenum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 };
584826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
585826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekclass FormatStringHandler {
586826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekpublic:
587826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  FormatStringHandler() {}
588826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  virtual ~FormatStringHandler();
589826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
590826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  virtual void HandleNullChar(const char *nullCharacter) {}
591826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
592f85626453123f9691bcef13cff963f556e209c27Hans Wennborg  virtual void HandlePosition(const char *startPos, unsigned posLen) {}
593f85626453123f9691bcef13cff963f556e209c27Hans Wennborg
594826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  virtual void HandleInvalidPosition(const char *startPos, unsigned posLen,
595826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                     PositionContext p) {}
596826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
597826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  virtual void HandleZeroPosition(const char *startPos, unsigned posLen) {}
598826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
599826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  virtual void HandleIncompleteSpecifier(const char *startSpecifier,
600826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                         unsigned specifierLen) {}
601826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
602826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  // Printf-specific handlers.
603826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
604826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  virtual bool HandleInvalidPrintfConversionSpecifier(
605826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                      const analyze_printf::PrintfSpecifier &FS,
606826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                      const char *startSpecifier,
607826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                      unsigned specifierLen) {
608826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return true;
609826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
610826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
611826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  virtual bool HandlePrintfSpecifier(const analyze_printf::PrintfSpecifier &FS,
612826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                     const char *startSpecifier,
613826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                     unsigned specifierLen) {
614826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return true;
615826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
616826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
617826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    // Scanf-specific handlers.
618826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
619826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  virtual bool HandleInvalidScanfConversionSpecifier(
620826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                        const analyze_scanf::ScanfSpecifier &FS,
621826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                        const char *startSpecifier,
622826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                        unsigned specifierLen) {
623826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return true;
624826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
625826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
626826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  virtual bool HandleScanfSpecifier(const analyze_scanf::ScanfSpecifier &FS,
627826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                    const char *startSpecifier,
628826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek                                    unsigned specifierLen) {
629826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek    return true;
630826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  }
631826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
632826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek  virtual void HandleIncompleteScanList(const char *start, const char *end) {}
633826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek};
634826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
635826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool ParsePrintfString(FormatStringHandler &H,
636275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose                       const char *beg, const char *end, const LangOptions &LO,
637275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose                       const TargetInfo &Target);
638826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
639826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenekbool ParseScanfString(FormatStringHandler &H,
640275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose                      const char *beg, const char *end, const LangOptions &LO,
641275b6f52c7bcafc1f3cf291813b5c60ee776965aJordan Rose                      const TargetInfo &Target);
642826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek
643826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek} // end analyze_format_string namespace
644826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek} // end clang namespace
645826a3457f737f1fc45a22954fd1bfde38160c165Ted Kremenek#endif
646