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