1f4a2713aSLionel Sambuc //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc // The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // Handling of format string in printf and friends. The structure of format
11f4a2713aSLionel Sambuc // strings for fprintf() are described in C99 7.19.6.1.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc
15f4a2713aSLionel Sambuc #include "clang/Analysis/Analyses/FormatString.h"
16f4a2713aSLionel Sambuc #include "FormatStringParsing.h"
17f4a2713aSLionel Sambuc #include "clang/Basic/TargetInfo.h"
18f4a2713aSLionel Sambuc
19f4a2713aSLionel Sambuc using clang::analyze_format_string::ArgType;
20f4a2713aSLionel Sambuc using clang::analyze_format_string::FormatStringHandler;
21f4a2713aSLionel Sambuc using clang::analyze_format_string::LengthModifier;
22f4a2713aSLionel Sambuc using clang::analyze_format_string::OptionalAmount;
23f4a2713aSLionel Sambuc using clang::analyze_format_string::ConversionSpecifier;
24f4a2713aSLionel Sambuc using clang::analyze_printf::PrintfSpecifier;
25f4a2713aSLionel Sambuc
26f4a2713aSLionel Sambuc using namespace clang;
27f4a2713aSLionel Sambuc
28f4a2713aSLionel Sambuc typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
29f4a2713aSLionel Sambuc PrintfSpecifierResult;
30f4a2713aSLionel Sambuc
31f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
32f4a2713aSLionel Sambuc // Methods for parsing format strings.
33f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
34f4a2713aSLionel Sambuc
35f4a2713aSLionel Sambuc using analyze_format_string::ParseNonPositionAmount;
36f4a2713aSLionel Sambuc
ParsePrecision(FormatStringHandler & H,PrintfSpecifier & FS,const char * Start,const char * & Beg,const char * E,unsigned * argIndex)37f4a2713aSLionel Sambuc static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
38f4a2713aSLionel Sambuc const char *Start, const char *&Beg, const char *E,
39f4a2713aSLionel Sambuc unsigned *argIndex) {
40f4a2713aSLionel Sambuc if (argIndex) {
41f4a2713aSLionel Sambuc FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
42f4a2713aSLionel Sambuc } else {
43f4a2713aSLionel Sambuc const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
44f4a2713aSLionel Sambuc analyze_format_string::PrecisionPos);
45f4a2713aSLionel Sambuc if (Amt.isInvalid())
46f4a2713aSLionel Sambuc return true;
47f4a2713aSLionel Sambuc FS.setPrecision(Amt);
48f4a2713aSLionel Sambuc }
49f4a2713aSLionel Sambuc return false;
50f4a2713aSLionel Sambuc }
51f4a2713aSLionel Sambuc
ParsePrintfSpecifier(FormatStringHandler & H,const char * & Beg,const char * E,unsigned & argIndex,const LangOptions & LO,const TargetInfo & Target,bool Warn)52f4a2713aSLionel Sambuc static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
53f4a2713aSLionel Sambuc const char *&Beg,
54f4a2713aSLionel Sambuc const char *E,
55f4a2713aSLionel Sambuc unsigned &argIndex,
56f4a2713aSLionel Sambuc const LangOptions &LO,
57*0a6a1f1dSLionel Sambuc const TargetInfo &Target,
58*0a6a1f1dSLionel Sambuc bool Warn) {
59f4a2713aSLionel Sambuc
60f4a2713aSLionel Sambuc using namespace clang::analyze_format_string;
61f4a2713aSLionel Sambuc using namespace clang::analyze_printf;
62f4a2713aSLionel Sambuc
63f4a2713aSLionel Sambuc const char *I = Beg;
64*0a6a1f1dSLionel Sambuc const char *Start = nullptr;
65f4a2713aSLionel Sambuc UpdateOnReturn <const char*> UpdateBeg(Beg, I);
66f4a2713aSLionel Sambuc
67f4a2713aSLionel Sambuc // Look for a '%' character that indicates the start of a format specifier.
68f4a2713aSLionel Sambuc for ( ; I != E ; ++I) {
69f4a2713aSLionel Sambuc char c = *I;
70f4a2713aSLionel Sambuc if (c == '\0') {
71f4a2713aSLionel Sambuc // Detect spurious null characters, which are likely errors.
72f4a2713aSLionel Sambuc H.HandleNullChar(I);
73f4a2713aSLionel Sambuc return true;
74f4a2713aSLionel Sambuc }
75f4a2713aSLionel Sambuc if (c == '%') {
76f4a2713aSLionel Sambuc Start = I++; // Record the start of the format specifier.
77f4a2713aSLionel Sambuc break;
78f4a2713aSLionel Sambuc }
79f4a2713aSLionel Sambuc }
80f4a2713aSLionel Sambuc
81f4a2713aSLionel Sambuc // No format specifier found?
82f4a2713aSLionel Sambuc if (!Start)
83f4a2713aSLionel Sambuc return false;
84f4a2713aSLionel Sambuc
85f4a2713aSLionel Sambuc if (I == E) {
86f4a2713aSLionel Sambuc // No more characters left?
87*0a6a1f1dSLionel Sambuc if (Warn)
88f4a2713aSLionel Sambuc H.HandleIncompleteSpecifier(Start, E - Start);
89f4a2713aSLionel Sambuc return true;
90f4a2713aSLionel Sambuc }
91f4a2713aSLionel Sambuc
92f4a2713aSLionel Sambuc PrintfSpecifier FS;
93f4a2713aSLionel Sambuc if (ParseArgPosition(H, FS, Start, I, E))
94f4a2713aSLionel Sambuc return true;
95f4a2713aSLionel Sambuc
96f4a2713aSLionel Sambuc if (I == E) {
97f4a2713aSLionel Sambuc // No more characters left?
98*0a6a1f1dSLionel Sambuc if (Warn)
99f4a2713aSLionel Sambuc H.HandleIncompleteSpecifier(Start, E - Start);
100f4a2713aSLionel Sambuc return true;
101f4a2713aSLionel Sambuc }
102f4a2713aSLionel Sambuc
103f4a2713aSLionel Sambuc // Look for flags (if any).
104f4a2713aSLionel Sambuc bool hasMore = true;
105f4a2713aSLionel Sambuc for ( ; I != E; ++I) {
106f4a2713aSLionel Sambuc switch (*I) {
107f4a2713aSLionel Sambuc default: hasMore = false; break;
108f4a2713aSLionel Sambuc case '\'':
109f4a2713aSLionel Sambuc // FIXME: POSIX specific. Always accept?
110f4a2713aSLionel Sambuc FS.setHasThousandsGrouping(I);
111f4a2713aSLionel Sambuc break;
112f4a2713aSLionel Sambuc case '-': FS.setIsLeftJustified(I); break;
113f4a2713aSLionel Sambuc case '+': FS.setHasPlusPrefix(I); break;
114f4a2713aSLionel Sambuc case ' ': FS.setHasSpacePrefix(I); break;
115f4a2713aSLionel Sambuc case '#': FS.setHasAlternativeForm(I); break;
116f4a2713aSLionel Sambuc case '0': FS.setHasLeadingZeros(I); break;
117f4a2713aSLionel Sambuc }
118f4a2713aSLionel Sambuc if (!hasMore)
119f4a2713aSLionel Sambuc break;
120f4a2713aSLionel Sambuc }
121f4a2713aSLionel Sambuc
122f4a2713aSLionel Sambuc if (I == E) {
123f4a2713aSLionel Sambuc // No more characters left?
124*0a6a1f1dSLionel Sambuc if (Warn)
125f4a2713aSLionel Sambuc H.HandleIncompleteSpecifier(Start, E - Start);
126f4a2713aSLionel Sambuc return true;
127f4a2713aSLionel Sambuc }
128f4a2713aSLionel Sambuc
129f4a2713aSLionel Sambuc // Look for the field width (if any).
130f4a2713aSLionel Sambuc if (ParseFieldWidth(H, FS, Start, I, E,
131*0a6a1f1dSLionel Sambuc FS.usesPositionalArg() ? nullptr : &argIndex))
132f4a2713aSLionel Sambuc return true;
133f4a2713aSLionel Sambuc
134f4a2713aSLionel Sambuc if (I == E) {
135f4a2713aSLionel Sambuc // No more characters left?
136*0a6a1f1dSLionel Sambuc if (Warn)
137f4a2713aSLionel Sambuc H.HandleIncompleteSpecifier(Start, E - Start);
138f4a2713aSLionel Sambuc return true;
139f4a2713aSLionel Sambuc }
140f4a2713aSLionel Sambuc
141f4a2713aSLionel Sambuc // Look for the precision (if any).
142f4a2713aSLionel Sambuc if (*I == '.') {
143f4a2713aSLionel Sambuc ++I;
144f4a2713aSLionel Sambuc if (I == E) {
145*0a6a1f1dSLionel Sambuc if (Warn)
146f4a2713aSLionel Sambuc H.HandleIncompleteSpecifier(Start, E - Start);
147f4a2713aSLionel Sambuc return true;
148f4a2713aSLionel Sambuc }
149f4a2713aSLionel Sambuc
150f4a2713aSLionel Sambuc if (ParsePrecision(H, FS, Start, I, E,
151*0a6a1f1dSLionel Sambuc FS.usesPositionalArg() ? nullptr : &argIndex))
152f4a2713aSLionel Sambuc return true;
153f4a2713aSLionel Sambuc
154f4a2713aSLionel Sambuc if (I == E) {
155f4a2713aSLionel Sambuc // No more characters left?
156*0a6a1f1dSLionel Sambuc if (Warn)
157f4a2713aSLionel Sambuc H.HandleIncompleteSpecifier(Start, E - Start);
158f4a2713aSLionel Sambuc return true;
159f4a2713aSLionel Sambuc }
160f4a2713aSLionel Sambuc }
161f4a2713aSLionel Sambuc
162f4a2713aSLionel Sambuc // Look for the length modifier.
163f4a2713aSLionel Sambuc if (ParseLengthModifier(FS, I, E, LO) && I == E) {
164f4a2713aSLionel Sambuc // No more characters left?
165*0a6a1f1dSLionel Sambuc if (Warn)
166f4a2713aSLionel Sambuc H.HandleIncompleteSpecifier(Start, E - Start);
167f4a2713aSLionel Sambuc return true;
168f4a2713aSLionel Sambuc }
169f4a2713aSLionel Sambuc
170f4a2713aSLionel Sambuc if (*I == '\0') {
171f4a2713aSLionel Sambuc // Detect spurious null characters, which are likely errors.
172f4a2713aSLionel Sambuc H.HandleNullChar(I);
173f4a2713aSLionel Sambuc return true;
174f4a2713aSLionel Sambuc }
175f4a2713aSLionel Sambuc
176f4a2713aSLionel Sambuc // Finally, look for the conversion specifier.
177f4a2713aSLionel Sambuc const char *conversionPosition = I++;
178f4a2713aSLionel Sambuc ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
179f4a2713aSLionel Sambuc switch (*conversionPosition) {
180f4a2713aSLionel Sambuc default:
181f4a2713aSLionel Sambuc break;
182f4a2713aSLionel Sambuc // C99: 7.19.6.1 (section 8).
183f4a2713aSLionel Sambuc case '%': k = ConversionSpecifier::PercentArg; break;
184f4a2713aSLionel Sambuc case 'A': k = ConversionSpecifier::AArg; break;
185f4a2713aSLionel Sambuc case 'E': k = ConversionSpecifier::EArg; break;
186f4a2713aSLionel Sambuc case 'F': k = ConversionSpecifier::FArg; break;
187f4a2713aSLionel Sambuc case 'G': k = ConversionSpecifier::GArg; break;
188f4a2713aSLionel Sambuc case 'X': k = ConversionSpecifier::XArg; break;
189f4a2713aSLionel Sambuc case 'a': k = ConversionSpecifier::aArg; break;
190f4a2713aSLionel Sambuc case 'c': k = ConversionSpecifier::cArg; break;
191f4a2713aSLionel Sambuc case 'd': k = ConversionSpecifier::dArg; break;
192f4a2713aSLionel Sambuc case 'e': k = ConversionSpecifier::eArg; break;
193f4a2713aSLionel Sambuc case 'f': k = ConversionSpecifier::fArg; break;
194f4a2713aSLionel Sambuc case 'g': k = ConversionSpecifier::gArg; break;
195f4a2713aSLionel Sambuc case 'i': k = ConversionSpecifier::iArg; break;
196f4a2713aSLionel Sambuc case 'n': k = ConversionSpecifier::nArg; break;
197f4a2713aSLionel Sambuc case 'o': k = ConversionSpecifier::oArg; break;
198f4a2713aSLionel Sambuc case 'p': k = ConversionSpecifier::pArg; break;
199f4a2713aSLionel Sambuc case 's': k = ConversionSpecifier::sArg; break;
200f4a2713aSLionel Sambuc case 'u': k = ConversionSpecifier::uArg; break;
201f4a2713aSLionel Sambuc case 'x': k = ConversionSpecifier::xArg; break;
202f4a2713aSLionel Sambuc // POSIX specific.
203f4a2713aSLionel Sambuc case 'C': k = ConversionSpecifier::CArg; break;
204f4a2713aSLionel Sambuc case 'S': k = ConversionSpecifier::SArg; break;
205f4a2713aSLionel Sambuc // Objective-C.
206f4a2713aSLionel Sambuc case '@': k = ConversionSpecifier::ObjCObjArg; break;
207f4a2713aSLionel Sambuc // Glibc specific.
208f4a2713aSLionel Sambuc case 'm': k = ConversionSpecifier::PrintErrno; break;
209*0a6a1f1dSLionel Sambuc // Apple-specific.
210f4a2713aSLionel Sambuc case 'D':
211f4a2713aSLionel Sambuc if (Target.getTriple().isOSDarwin())
212f4a2713aSLionel Sambuc k = ConversionSpecifier::DArg;
213f4a2713aSLionel Sambuc break;
214f4a2713aSLionel Sambuc case 'O':
215f4a2713aSLionel Sambuc if (Target.getTriple().isOSDarwin())
216f4a2713aSLionel Sambuc k = ConversionSpecifier::OArg;
217f4a2713aSLionel Sambuc break;
218f4a2713aSLionel Sambuc case 'U':
219f4a2713aSLionel Sambuc if (Target.getTriple().isOSDarwin())
220f4a2713aSLionel Sambuc k = ConversionSpecifier::UArg;
221f4a2713aSLionel Sambuc break;
222*0a6a1f1dSLionel Sambuc // MS specific.
223*0a6a1f1dSLionel Sambuc case 'Z':
224*0a6a1f1dSLionel Sambuc if (Target.getTriple().isOSMSVCRT())
225*0a6a1f1dSLionel Sambuc k = ConversionSpecifier::ZArg;
226f4a2713aSLionel Sambuc }
227f4a2713aSLionel Sambuc PrintfConversionSpecifier CS(conversionPosition, k);
228f4a2713aSLionel Sambuc FS.setConversionSpecifier(CS);
229f4a2713aSLionel Sambuc if (CS.consumesDataArgument() && !FS.usesPositionalArg())
230f4a2713aSLionel Sambuc FS.setArgIndex(argIndex++);
231f4a2713aSLionel Sambuc
232f4a2713aSLionel Sambuc if (k == ConversionSpecifier::InvalidSpecifier) {
233f4a2713aSLionel Sambuc // Assume the conversion takes one argument.
234f4a2713aSLionel Sambuc return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
235f4a2713aSLionel Sambuc }
236f4a2713aSLionel Sambuc return PrintfSpecifierResult(Start, FS);
237f4a2713aSLionel Sambuc }
238f4a2713aSLionel Sambuc
ParsePrintfString(FormatStringHandler & H,const char * I,const char * E,const LangOptions & LO,const TargetInfo & Target)239f4a2713aSLionel Sambuc bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
240f4a2713aSLionel Sambuc const char *I,
241f4a2713aSLionel Sambuc const char *E,
242f4a2713aSLionel Sambuc const LangOptions &LO,
243f4a2713aSLionel Sambuc const TargetInfo &Target) {
244f4a2713aSLionel Sambuc
245f4a2713aSLionel Sambuc unsigned argIndex = 0;
246f4a2713aSLionel Sambuc
247f4a2713aSLionel Sambuc // Keep looking for a format specifier until we have exhausted the string.
248f4a2713aSLionel Sambuc while (I != E) {
249f4a2713aSLionel Sambuc const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
250*0a6a1f1dSLionel Sambuc LO, Target, true);
251f4a2713aSLionel Sambuc // Did a fail-stop error of any kind occur when parsing the specifier?
252f4a2713aSLionel Sambuc // If so, don't do any more processing.
253f4a2713aSLionel Sambuc if (FSR.shouldStop())
254f4a2713aSLionel Sambuc return true;
255f4a2713aSLionel Sambuc // Did we exhaust the string or encounter an error that
256f4a2713aSLionel Sambuc // we can recover from?
257f4a2713aSLionel Sambuc if (!FSR.hasValue())
258f4a2713aSLionel Sambuc continue;
259f4a2713aSLionel Sambuc // We have a format specifier. Pass it to the callback.
260f4a2713aSLionel Sambuc if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
261f4a2713aSLionel Sambuc I - FSR.getStart()))
262f4a2713aSLionel Sambuc return true;
263f4a2713aSLionel Sambuc }
264f4a2713aSLionel Sambuc assert(I == E && "Format string not exhausted");
265f4a2713aSLionel Sambuc return false;
266f4a2713aSLionel Sambuc }
267f4a2713aSLionel Sambuc
ParseFormatStringHasSArg(const char * I,const char * E,const LangOptions & LO,const TargetInfo & Target)268*0a6a1f1dSLionel Sambuc bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
269*0a6a1f1dSLionel Sambuc const char *E,
270*0a6a1f1dSLionel Sambuc const LangOptions &LO,
271*0a6a1f1dSLionel Sambuc const TargetInfo &Target) {
272*0a6a1f1dSLionel Sambuc
273*0a6a1f1dSLionel Sambuc unsigned argIndex = 0;
274*0a6a1f1dSLionel Sambuc
275*0a6a1f1dSLionel Sambuc // Keep looking for a %s format specifier until we have exhausted the string.
276*0a6a1f1dSLionel Sambuc FormatStringHandler H;
277*0a6a1f1dSLionel Sambuc while (I != E) {
278*0a6a1f1dSLionel Sambuc const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
279*0a6a1f1dSLionel Sambuc LO, Target, false);
280*0a6a1f1dSLionel Sambuc // Did a fail-stop error of any kind occur when parsing the specifier?
281*0a6a1f1dSLionel Sambuc // If so, don't do any more processing.
282*0a6a1f1dSLionel Sambuc if (FSR.shouldStop())
283*0a6a1f1dSLionel Sambuc return false;
284*0a6a1f1dSLionel Sambuc // Did we exhaust the string or encounter an error that
285*0a6a1f1dSLionel Sambuc // we can recover from?
286*0a6a1f1dSLionel Sambuc if (!FSR.hasValue())
287*0a6a1f1dSLionel Sambuc continue;
288*0a6a1f1dSLionel Sambuc const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
289*0a6a1f1dSLionel Sambuc // Return true if this a %s format specifier.
290*0a6a1f1dSLionel Sambuc if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
291*0a6a1f1dSLionel Sambuc return true;
292*0a6a1f1dSLionel Sambuc }
293*0a6a1f1dSLionel Sambuc return false;
294*0a6a1f1dSLionel Sambuc }
295*0a6a1f1dSLionel Sambuc
296f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
297f4a2713aSLionel Sambuc // Methods on PrintfSpecifier.
298f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
299f4a2713aSLionel Sambuc
getArgType(ASTContext & Ctx,bool IsObjCLiteral) const300f4a2713aSLionel Sambuc ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
301f4a2713aSLionel Sambuc bool IsObjCLiteral) const {
302f4a2713aSLionel Sambuc const PrintfConversionSpecifier &CS = getConversionSpecifier();
303f4a2713aSLionel Sambuc
304f4a2713aSLionel Sambuc if (!CS.consumesDataArgument())
305f4a2713aSLionel Sambuc return ArgType::Invalid();
306f4a2713aSLionel Sambuc
307f4a2713aSLionel Sambuc if (CS.getKind() == ConversionSpecifier::cArg)
308f4a2713aSLionel Sambuc switch (LM.getKind()) {
309*0a6a1f1dSLionel Sambuc case LengthModifier::None:
310*0a6a1f1dSLionel Sambuc return Ctx.IntTy;
311f4a2713aSLionel Sambuc case LengthModifier::AsLong:
312*0a6a1f1dSLionel Sambuc case LengthModifier::AsWide:
313f4a2713aSLionel Sambuc return ArgType(ArgType::WIntTy, "wint_t");
314*0a6a1f1dSLionel Sambuc case LengthModifier::AsShort:
315*0a6a1f1dSLionel Sambuc if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
316*0a6a1f1dSLionel Sambuc return Ctx.IntTy;
317f4a2713aSLionel Sambuc default:
318f4a2713aSLionel Sambuc return ArgType::Invalid();
319f4a2713aSLionel Sambuc }
320f4a2713aSLionel Sambuc
321f4a2713aSLionel Sambuc if (CS.isIntArg())
322f4a2713aSLionel Sambuc switch (LM.getKind()) {
323f4a2713aSLionel Sambuc case LengthModifier::AsLongDouble:
324f4a2713aSLionel Sambuc // GNU extension.
325f4a2713aSLionel Sambuc return Ctx.LongLongTy;
326f4a2713aSLionel Sambuc case LengthModifier::None:
327f4a2713aSLionel Sambuc return Ctx.IntTy;
328f4a2713aSLionel Sambuc case LengthModifier::AsInt32:
329f4a2713aSLionel Sambuc return ArgType(Ctx.IntTy, "__int32");
330f4a2713aSLionel Sambuc case LengthModifier::AsChar: return ArgType::AnyCharTy;
331f4a2713aSLionel Sambuc case LengthModifier::AsShort: return Ctx.ShortTy;
332f4a2713aSLionel Sambuc case LengthModifier::AsLong: return Ctx.LongTy;
333f4a2713aSLionel Sambuc case LengthModifier::AsLongLong:
334f4a2713aSLionel Sambuc case LengthModifier::AsQuad:
335f4a2713aSLionel Sambuc return Ctx.LongLongTy;
336f4a2713aSLionel Sambuc case LengthModifier::AsInt64:
337f4a2713aSLionel Sambuc return ArgType(Ctx.LongLongTy, "__int64");
338f4a2713aSLionel Sambuc case LengthModifier::AsIntMax:
339f4a2713aSLionel Sambuc return ArgType(Ctx.getIntMaxType(), "intmax_t");
340f4a2713aSLionel Sambuc case LengthModifier::AsSizeT:
341f4a2713aSLionel Sambuc // FIXME: How to get the corresponding signed version of size_t?
342f4a2713aSLionel Sambuc return ArgType();
343f4a2713aSLionel Sambuc case LengthModifier::AsInt3264:
344f4a2713aSLionel Sambuc return Ctx.getTargetInfo().getTriple().isArch64Bit()
345f4a2713aSLionel Sambuc ? ArgType(Ctx.LongLongTy, "__int64")
346f4a2713aSLionel Sambuc : ArgType(Ctx.IntTy, "__int32");
347f4a2713aSLionel Sambuc case LengthModifier::AsPtrDiff:
348f4a2713aSLionel Sambuc return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
349f4a2713aSLionel Sambuc case LengthModifier::AsAllocate:
350f4a2713aSLionel Sambuc case LengthModifier::AsMAllocate:
351*0a6a1f1dSLionel Sambuc case LengthModifier::AsWide:
352f4a2713aSLionel Sambuc return ArgType::Invalid();
353f4a2713aSLionel Sambuc }
354f4a2713aSLionel Sambuc
355f4a2713aSLionel Sambuc if (CS.isUIntArg())
356f4a2713aSLionel Sambuc switch (LM.getKind()) {
357f4a2713aSLionel Sambuc case LengthModifier::AsLongDouble:
358f4a2713aSLionel Sambuc // GNU extension.
359f4a2713aSLionel Sambuc return Ctx.UnsignedLongLongTy;
360f4a2713aSLionel Sambuc case LengthModifier::None:
361f4a2713aSLionel Sambuc return Ctx.UnsignedIntTy;
362f4a2713aSLionel Sambuc case LengthModifier::AsInt32:
363f4a2713aSLionel Sambuc return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
364f4a2713aSLionel Sambuc case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
365f4a2713aSLionel Sambuc case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
366f4a2713aSLionel Sambuc case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
367f4a2713aSLionel Sambuc case LengthModifier::AsLongLong:
368f4a2713aSLionel Sambuc case LengthModifier::AsQuad:
369f4a2713aSLionel Sambuc return Ctx.UnsignedLongLongTy;
370f4a2713aSLionel Sambuc case LengthModifier::AsInt64:
371f4a2713aSLionel Sambuc return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
372f4a2713aSLionel Sambuc case LengthModifier::AsIntMax:
373f4a2713aSLionel Sambuc return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
374f4a2713aSLionel Sambuc case LengthModifier::AsSizeT:
375f4a2713aSLionel Sambuc return ArgType(Ctx.getSizeType(), "size_t");
376f4a2713aSLionel Sambuc case LengthModifier::AsInt3264:
377f4a2713aSLionel Sambuc return Ctx.getTargetInfo().getTriple().isArch64Bit()
378f4a2713aSLionel Sambuc ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
379f4a2713aSLionel Sambuc : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
380f4a2713aSLionel Sambuc case LengthModifier::AsPtrDiff:
381f4a2713aSLionel Sambuc // FIXME: How to get the corresponding unsigned
382f4a2713aSLionel Sambuc // version of ptrdiff_t?
383f4a2713aSLionel Sambuc return ArgType();
384f4a2713aSLionel Sambuc case LengthModifier::AsAllocate:
385f4a2713aSLionel Sambuc case LengthModifier::AsMAllocate:
386*0a6a1f1dSLionel Sambuc case LengthModifier::AsWide:
387f4a2713aSLionel Sambuc return ArgType::Invalid();
388f4a2713aSLionel Sambuc }
389f4a2713aSLionel Sambuc
390f4a2713aSLionel Sambuc if (CS.isDoubleArg()) {
391f4a2713aSLionel Sambuc if (LM.getKind() == LengthModifier::AsLongDouble)
392f4a2713aSLionel Sambuc return Ctx.LongDoubleTy;
393f4a2713aSLionel Sambuc return Ctx.DoubleTy;
394f4a2713aSLionel Sambuc }
395f4a2713aSLionel Sambuc
396f4a2713aSLionel Sambuc if (CS.getKind() == ConversionSpecifier::nArg) {
397f4a2713aSLionel Sambuc switch (LM.getKind()) {
398f4a2713aSLionel Sambuc case LengthModifier::None:
399f4a2713aSLionel Sambuc return ArgType::PtrTo(Ctx.IntTy);
400f4a2713aSLionel Sambuc case LengthModifier::AsChar:
401f4a2713aSLionel Sambuc return ArgType::PtrTo(Ctx.SignedCharTy);
402f4a2713aSLionel Sambuc case LengthModifier::AsShort:
403f4a2713aSLionel Sambuc return ArgType::PtrTo(Ctx.ShortTy);
404f4a2713aSLionel Sambuc case LengthModifier::AsLong:
405f4a2713aSLionel Sambuc return ArgType::PtrTo(Ctx.LongTy);
406f4a2713aSLionel Sambuc case LengthModifier::AsLongLong:
407f4a2713aSLionel Sambuc case LengthModifier::AsQuad:
408f4a2713aSLionel Sambuc return ArgType::PtrTo(Ctx.LongLongTy);
409f4a2713aSLionel Sambuc case LengthModifier::AsIntMax:
410f4a2713aSLionel Sambuc return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
411f4a2713aSLionel Sambuc case LengthModifier::AsSizeT:
412f4a2713aSLionel Sambuc return ArgType(); // FIXME: ssize_t
413f4a2713aSLionel Sambuc case LengthModifier::AsPtrDiff:
414f4a2713aSLionel Sambuc return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
415f4a2713aSLionel Sambuc case LengthModifier::AsLongDouble:
416f4a2713aSLionel Sambuc return ArgType(); // FIXME: Is this a known extension?
417f4a2713aSLionel Sambuc case LengthModifier::AsAllocate:
418f4a2713aSLionel Sambuc case LengthModifier::AsMAllocate:
419f4a2713aSLionel Sambuc case LengthModifier::AsInt32:
420f4a2713aSLionel Sambuc case LengthModifier::AsInt3264:
421f4a2713aSLionel Sambuc case LengthModifier::AsInt64:
422*0a6a1f1dSLionel Sambuc case LengthModifier::AsWide:
423f4a2713aSLionel Sambuc return ArgType::Invalid();
424f4a2713aSLionel Sambuc }
425f4a2713aSLionel Sambuc }
426f4a2713aSLionel Sambuc
427f4a2713aSLionel Sambuc switch (CS.getKind()) {
428f4a2713aSLionel Sambuc case ConversionSpecifier::sArg:
429f4a2713aSLionel Sambuc if (LM.getKind() == LengthModifier::AsWideChar) {
430f4a2713aSLionel Sambuc if (IsObjCLiteral)
431f4a2713aSLionel Sambuc return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
432f4a2713aSLionel Sambuc "const unichar *");
433f4a2713aSLionel Sambuc return ArgType(ArgType::WCStrTy, "wchar_t *");
434f4a2713aSLionel Sambuc }
435*0a6a1f1dSLionel Sambuc if (LM.getKind() == LengthModifier::AsWide)
436*0a6a1f1dSLionel Sambuc return ArgType(ArgType::WCStrTy, "wchar_t *");
437f4a2713aSLionel Sambuc return ArgType::CStrTy;
438f4a2713aSLionel Sambuc case ConversionSpecifier::SArg:
439f4a2713aSLionel Sambuc if (IsObjCLiteral)
440f4a2713aSLionel Sambuc return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
441f4a2713aSLionel Sambuc "const unichar *");
442*0a6a1f1dSLionel Sambuc if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
443*0a6a1f1dSLionel Sambuc LM.getKind() == LengthModifier::AsShort)
444*0a6a1f1dSLionel Sambuc return ArgType::CStrTy;
445f4a2713aSLionel Sambuc return ArgType(ArgType::WCStrTy, "wchar_t *");
446f4a2713aSLionel Sambuc case ConversionSpecifier::CArg:
447f4a2713aSLionel Sambuc if (IsObjCLiteral)
448f4a2713aSLionel Sambuc return ArgType(Ctx.UnsignedShortTy, "unichar");
449*0a6a1f1dSLionel Sambuc if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
450*0a6a1f1dSLionel Sambuc LM.getKind() == LengthModifier::AsShort)
451*0a6a1f1dSLionel Sambuc return Ctx.IntTy;
452f4a2713aSLionel Sambuc return ArgType(Ctx.WideCharTy, "wchar_t");
453f4a2713aSLionel Sambuc case ConversionSpecifier::pArg:
454f4a2713aSLionel Sambuc return ArgType::CPointerTy;
455f4a2713aSLionel Sambuc case ConversionSpecifier::ObjCObjArg:
456f4a2713aSLionel Sambuc return ArgType::ObjCPointerTy;
457f4a2713aSLionel Sambuc default:
458f4a2713aSLionel Sambuc break;
459f4a2713aSLionel Sambuc }
460f4a2713aSLionel Sambuc
461f4a2713aSLionel Sambuc // FIXME: Handle other cases.
462f4a2713aSLionel Sambuc return ArgType();
463f4a2713aSLionel Sambuc }
464f4a2713aSLionel Sambuc
fixType(QualType QT,const LangOptions & LangOpt,ASTContext & Ctx,bool IsObjCLiteral)465f4a2713aSLionel Sambuc bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
466f4a2713aSLionel Sambuc ASTContext &Ctx, bool IsObjCLiteral) {
467f4a2713aSLionel Sambuc // %n is different from other conversion specifiers; don't try to fix it.
468f4a2713aSLionel Sambuc if (CS.getKind() == ConversionSpecifier::nArg)
469f4a2713aSLionel Sambuc return false;
470f4a2713aSLionel Sambuc
471f4a2713aSLionel Sambuc // Handle Objective-C objects first. Note that while the '%@' specifier will
472f4a2713aSLionel Sambuc // not warn for structure pointer or void pointer arguments (because that's
473f4a2713aSLionel Sambuc // how CoreFoundation objects are implemented), we only show a fixit for '%@'
474f4a2713aSLionel Sambuc // if we know it's an object (block, id, class, or __attribute__((NSObject))).
475f4a2713aSLionel Sambuc if (QT->isObjCRetainableType()) {
476f4a2713aSLionel Sambuc if (!IsObjCLiteral)
477f4a2713aSLionel Sambuc return false;
478f4a2713aSLionel Sambuc
479f4a2713aSLionel Sambuc CS.setKind(ConversionSpecifier::ObjCObjArg);
480f4a2713aSLionel Sambuc
481f4a2713aSLionel Sambuc // Disable irrelevant flags
482f4a2713aSLionel Sambuc HasThousandsGrouping = false;
483f4a2713aSLionel Sambuc HasPlusPrefix = false;
484f4a2713aSLionel Sambuc HasSpacePrefix = false;
485f4a2713aSLionel Sambuc HasAlternativeForm = false;
486f4a2713aSLionel Sambuc HasLeadingZeroes = false;
487f4a2713aSLionel Sambuc Precision.setHowSpecified(OptionalAmount::NotSpecified);
488f4a2713aSLionel Sambuc LM.setKind(LengthModifier::None);
489f4a2713aSLionel Sambuc
490f4a2713aSLionel Sambuc return true;
491f4a2713aSLionel Sambuc }
492f4a2713aSLionel Sambuc
493f4a2713aSLionel Sambuc // Handle strings next (char *, wchar_t *)
494f4a2713aSLionel Sambuc if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
495f4a2713aSLionel Sambuc CS.setKind(ConversionSpecifier::sArg);
496f4a2713aSLionel Sambuc
497f4a2713aSLionel Sambuc // Disable irrelevant flags
498f4a2713aSLionel Sambuc HasAlternativeForm = 0;
499f4a2713aSLionel Sambuc HasLeadingZeroes = 0;
500f4a2713aSLionel Sambuc
501f4a2713aSLionel Sambuc // Set the long length modifier for wide characters
502f4a2713aSLionel Sambuc if (QT->getPointeeType()->isWideCharType())
503f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsWideChar);
504f4a2713aSLionel Sambuc else
505f4a2713aSLionel Sambuc LM.setKind(LengthModifier::None);
506f4a2713aSLionel Sambuc
507f4a2713aSLionel Sambuc return true;
508f4a2713aSLionel Sambuc }
509f4a2713aSLionel Sambuc
510f4a2713aSLionel Sambuc // If it's an enum, get its underlying type.
511f4a2713aSLionel Sambuc if (const EnumType *ETy = QT->getAs<EnumType>())
512f4a2713aSLionel Sambuc QT = ETy->getDecl()->getIntegerType();
513f4a2713aSLionel Sambuc
514f4a2713aSLionel Sambuc // We can only work with builtin types.
515f4a2713aSLionel Sambuc const BuiltinType *BT = QT->getAs<BuiltinType>();
516f4a2713aSLionel Sambuc if (!BT)
517f4a2713aSLionel Sambuc return false;
518f4a2713aSLionel Sambuc
519f4a2713aSLionel Sambuc // Set length modifier
520f4a2713aSLionel Sambuc switch (BT->getKind()) {
521f4a2713aSLionel Sambuc case BuiltinType::Bool:
522f4a2713aSLionel Sambuc case BuiltinType::WChar_U:
523f4a2713aSLionel Sambuc case BuiltinType::WChar_S:
524f4a2713aSLionel Sambuc case BuiltinType::Char16:
525f4a2713aSLionel Sambuc case BuiltinType::Char32:
526f4a2713aSLionel Sambuc case BuiltinType::UInt128:
527f4a2713aSLionel Sambuc case BuiltinType::Int128:
528f4a2713aSLionel Sambuc case BuiltinType::Half:
529f4a2713aSLionel Sambuc // Various types which are non-trivial to correct.
530f4a2713aSLionel Sambuc return false;
531f4a2713aSLionel Sambuc
532f4a2713aSLionel Sambuc #define SIGNED_TYPE(Id, SingletonId)
533f4a2713aSLionel Sambuc #define UNSIGNED_TYPE(Id, SingletonId)
534f4a2713aSLionel Sambuc #define FLOATING_TYPE(Id, SingletonId)
535f4a2713aSLionel Sambuc #define BUILTIN_TYPE(Id, SingletonId) \
536f4a2713aSLionel Sambuc case BuiltinType::Id:
537f4a2713aSLionel Sambuc #include "clang/AST/BuiltinTypes.def"
538f4a2713aSLionel Sambuc // Misc other stuff which doesn't make sense here.
539f4a2713aSLionel Sambuc return false;
540f4a2713aSLionel Sambuc
541f4a2713aSLionel Sambuc case BuiltinType::UInt:
542f4a2713aSLionel Sambuc case BuiltinType::Int:
543f4a2713aSLionel Sambuc case BuiltinType::Float:
544f4a2713aSLionel Sambuc case BuiltinType::Double:
545f4a2713aSLionel Sambuc LM.setKind(LengthModifier::None);
546f4a2713aSLionel Sambuc break;
547f4a2713aSLionel Sambuc
548f4a2713aSLionel Sambuc case BuiltinType::Char_U:
549f4a2713aSLionel Sambuc case BuiltinType::UChar:
550f4a2713aSLionel Sambuc case BuiltinType::Char_S:
551f4a2713aSLionel Sambuc case BuiltinType::SChar:
552f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsChar);
553f4a2713aSLionel Sambuc break;
554f4a2713aSLionel Sambuc
555f4a2713aSLionel Sambuc case BuiltinType::Short:
556f4a2713aSLionel Sambuc case BuiltinType::UShort:
557f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsShort);
558f4a2713aSLionel Sambuc break;
559f4a2713aSLionel Sambuc
560f4a2713aSLionel Sambuc case BuiltinType::Long:
561f4a2713aSLionel Sambuc case BuiltinType::ULong:
562f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsLong);
563f4a2713aSLionel Sambuc break;
564f4a2713aSLionel Sambuc
565f4a2713aSLionel Sambuc case BuiltinType::LongLong:
566f4a2713aSLionel Sambuc case BuiltinType::ULongLong:
567f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsLongLong);
568f4a2713aSLionel Sambuc break;
569f4a2713aSLionel Sambuc
570f4a2713aSLionel Sambuc case BuiltinType::LongDouble:
571f4a2713aSLionel Sambuc LM.setKind(LengthModifier::AsLongDouble);
572f4a2713aSLionel Sambuc break;
573f4a2713aSLionel Sambuc }
574f4a2713aSLionel Sambuc
575f4a2713aSLionel Sambuc // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
576f4a2713aSLionel Sambuc if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
577f4a2713aSLionel Sambuc namedTypeToLengthModifier(QT, LM);
578f4a2713aSLionel Sambuc
579f4a2713aSLionel Sambuc // If fixing the length modifier was enough, we might be done.
580f4a2713aSLionel Sambuc if (hasValidLengthModifier(Ctx.getTargetInfo())) {
581f4a2713aSLionel Sambuc // If we're going to offer a fix anyway, make sure the sign matches.
582f4a2713aSLionel Sambuc switch (CS.getKind()) {
583f4a2713aSLionel Sambuc case ConversionSpecifier::uArg:
584f4a2713aSLionel Sambuc case ConversionSpecifier::UArg:
585f4a2713aSLionel Sambuc if (QT->isSignedIntegerType())
586f4a2713aSLionel Sambuc CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
587f4a2713aSLionel Sambuc break;
588f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
589f4a2713aSLionel Sambuc case ConversionSpecifier::DArg:
590f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
591f4a2713aSLionel Sambuc if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
592f4a2713aSLionel Sambuc CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
593f4a2713aSLionel Sambuc break;
594f4a2713aSLionel Sambuc default:
595f4a2713aSLionel Sambuc // Other specifiers do not have signed/unsigned variants.
596f4a2713aSLionel Sambuc break;
597f4a2713aSLionel Sambuc }
598f4a2713aSLionel Sambuc
599f4a2713aSLionel Sambuc const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
600f4a2713aSLionel Sambuc if (ATR.isValid() && ATR.matchesType(Ctx, QT))
601f4a2713aSLionel Sambuc return true;
602f4a2713aSLionel Sambuc }
603f4a2713aSLionel Sambuc
604f4a2713aSLionel Sambuc // Set conversion specifier and disable any flags which do not apply to it.
605f4a2713aSLionel Sambuc // Let typedefs to char fall through to int, as %c is silly for uint8_t.
606f4a2713aSLionel Sambuc if (!isa<TypedefType>(QT) && QT->isCharType()) {
607f4a2713aSLionel Sambuc CS.setKind(ConversionSpecifier::cArg);
608f4a2713aSLionel Sambuc LM.setKind(LengthModifier::None);
609f4a2713aSLionel Sambuc Precision.setHowSpecified(OptionalAmount::NotSpecified);
610f4a2713aSLionel Sambuc HasAlternativeForm = 0;
611f4a2713aSLionel Sambuc HasLeadingZeroes = 0;
612f4a2713aSLionel Sambuc HasPlusPrefix = 0;
613f4a2713aSLionel Sambuc }
614f4a2713aSLionel Sambuc // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
615f4a2713aSLionel Sambuc else if (QT->isRealFloatingType()) {
616f4a2713aSLionel Sambuc CS.setKind(ConversionSpecifier::fArg);
617f4a2713aSLionel Sambuc }
618f4a2713aSLionel Sambuc else if (QT->isSignedIntegerType()) {
619f4a2713aSLionel Sambuc CS.setKind(ConversionSpecifier::dArg);
620f4a2713aSLionel Sambuc HasAlternativeForm = 0;
621f4a2713aSLionel Sambuc }
622f4a2713aSLionel Sambuc else if (QT->isUnsignedIntegerType()) {
623f4a2713aSLionel Sambuc CS.setKind(ConversionSpecifier::uArg);
624f4a2713aSLionel Sambuc HasAlternativeForm = 0;
625f4a2713aSLionel Sambuc HasPlusPrefix = 0;
626f4a2713aSLionel Sambuc } else {
627f4a2713aSLionel Sambuc llvm_unreachable("Unexpected type");
628f4a2713aSLionel Sambuc }
629f4a2713aSLionel Sambuc
630f4a2713aSLionel Sambuc return true;
631f4a2713aSLionel Sambuc }
632f4a2713aSLionel Sambuc
toString(raw_ostream & os) const633f4a2713aSLionel Sambuc void PrintfSpecifier::toString(raw_ostream &os) const {
634f4a2713aSLionel Sambuc // Whilst some features have no defined order, we are using the order
635f4a2713aSLionel Sambuc // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
636f4a2713aSLionel Sambuc os << "%";
637f4a2713aSLionel Sambuc
638f4a2713aSLionel Sambuc // Positional args
639f4a2713aSLionel Sambuc if (usesPositionalArg()) {
640f4a2713aSLionel Sambuc os << getPositionalArgIndex() << "$";
641f4a2713aSLionel Sambuc }
642f4a2713aSLionel Sambuc
643f4a2713aSLionel Sambuc // Conversion flags
644f4a2713aSLionel Sambuc if (IsLeftJustified) os << "-";
645f4a2713aSLionel Sambuc if (HasPlusPrefix) os << "+";
646f4a2713aSLionel Sambuc if (HasSpacePrefix) os << " ";
647f4a2713aSLionel Sambuc if (HasAlternativeForm) os << "#";
648f4a2713aSLionel Sambuc if (HasLeadingZeroes) os << "0";
649f4a2713aSLionel Sambuc
650f4a2713aSLionel Sambuc // Minimum field width
651f4a2713aSLionel Sambuc FieldWidth.toString(os);
652f4a2713aSLionel Sambuc // Precision
653f4a2713aSLionel Sambuc Precision.toString(os);
654f4a2713aSLionel Sambuc // Length modifier
655f4a2713aSLionel Sambuc os << LM.toString();
656f4a2713aSLionel Sambuc // Conversion specifier
657f4a2713aSLionel Sambuc os << CS.toString();
658f4a2713aSLionel Sambuc }
659f4a2713aSLionel Sambuc
hasValidPlusPrefix() const660f4a2713aSLionel Sambuc bool PrintfSpecifier::hasValidPlusPrefix() const {
661f4a2713aSLionel Sambuc if (!HasPlusPrefix)
662f4a2713aSLionel Sambuc return true;
663f4a2713aSLionel Sambuc
664f4a2713aSLionel Sambuc // The plus prefix only makes sense for signed conversions
665f4a2713aSLionel Sambuc switch (CS.getKind()) {
666f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
667f4a2713aSLionel Sambuc case ConversionSpecifier::DArg:
668f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
669f4a2713aSLionel Sambuc case ConversionSpecifier::fArg:
670f4a2713aSLionel Sambuc case ConversionSpecifier::FArg:
671f4a2713aSLionel Sambuc case ConversionSpecifier::eArg:
672f4a2713aSLionel Sambuc case ConversionSpecifier::EArg:
673f4a2713aSLionel Sambuc case ConversionSpecifier::gArg:
674f4a2713aSLionel Sambuc case ConversionSpecifier::GArg:
675f4a2713aSLionel Sambuc case ConversionSpecifier::aArg:
676f4a2713aSLionel Sambuc case ConversionSpecifier::AArg:
677f4a2713aSLionel Sambuc return true;
678f4a2713aSLionel Sambuc
679f4a2713aSLionel Sambuc default:
680f4a2713aSLionel Sambuc return false;
681f4a2713aSLionel Sambuc }
682f4a2713aSLionel Sambuc }
683f4a2713aSLionel Sambuc
hasValidAlternativeForm() const684f4a2713aSLionel Sambuc bool PrintfSpecifier::hasValidAlternativeForm() const {
685f4a2713aSLionel Sambuc if (!HasAlternativeForm)
686f4a2713aSLionel Sambuc return true;
687f4a2713aSLionel Sambuc
688f4a2713aSLionel Sambuc // Alternate form flag only valid with the oxXaAeEfFgG conversions
689f4a2713aSLionel Sambuc switch (CS.getKind()) {
690f4a2713aSLionel Sambuc case ConversionSpecifier::oArg:
691f4a2713aSLionel Sambuc case ConversionSpecifier::OArg:
692f4a2713aSLionel Sambuc case ConversionSpecifier::xArg:
693f4a2713aSLionel Sambuc case ConversionSpecifier::XArg:
694f4a2713aSLionel Sambuc case ConversionSpecifier::aArg:
695f4a2713aSLionel Sambuc case ConversionSpecifier::AArg:
696f4a2713aSLionel Sambuc case ConversionSpecifier::eArg:
697f4a2713aSLionel Sambuc case ConversionSpecifier::EArg:
698f4a2713aSLionel Sambuc case ConversionSpecifier::fArg:
699f4a2713aSLionel Sambuc case ConversionSpecifier::FArg:
700f4a2713aSLionel Sambuc case ConversionSpecifier::gArg:
701f4a2713aSLionel Sambuc case ConversionSpecifier::GArg:
702f4a2713aSLionel Sambuc return true;
703f4a2713aSLionel Sambuc
704f4a2713aSLionel Sambuc default:
705f4a2713aSLionel Sambuc return false;
706f4a2713aSLionel Sambuc }
707f4a2713aSLionel Sambuc }
708f4a2713aSLionel Sambuc
hasValidLeadingZeros() const709f4a2713aSLionel Sambuc bool PrintfSpecifier::hasValidLeadingZeros() const {
710f4a2713aSLionel Sambuc if (!HasLeadingZeroes)
711f4a2713aSLionel Sambuc return true;
712f4a2713aSLionel Sambuc
713f4a2713aSLionel Sambuc // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
714f4a2713aSLionel Sambuc switch (CS.getKind()) {
715f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
716f4a2713aSLionel Sambuc case ConversionSpecifier::DArg:
717f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
718f4a2713aSLionel Sambuc case ConversionSpecifier::oArg:
719f4a2713aSLionel Sambuc case ConversionSpecifier::OArg:
720f4a2713aSLionel Sambuc case ConversionSpecifier::uArg:
721f4a2713aSLionel Sambuc case ConversionSpecifier::UArg:
722f4a2713aSLionel Sambuc case ConversionSpecifier::xArg:
723f4a2713aSLionel Sambuc case ConversionSpecifier::XArg:
724f4a2713aSLionel Sambuc case ConversionSpecifier::aArg:
725f4a2713aSLionel Sambuc case ConversionSpecifier::AArg:
726f4a2713aSLionel Sambuc case ConversionSpecifier::eArg:
727f4a2713aSLionel Sambuc case ConversionSpecifier::EArg:
728f4a2713aSLionel Sambuc case ConversionSpecifier::fArg:
729f4a2713aSLionel Sambuc case ConversionSpecifier::FArg:
730f4a2713aSLionel Sambuc case ConversionSpecifier::gArg:
731f4a2713aSLionel Sambuc case ConversionSpecifier::GArg:
732f4a2713aSLionel Sambuc return true;
733f4a2713aSLionel Sambuc
734f4a2713aSLionel Sambuc default:
735f4a2713aSLionel Sambuc return false;
736f4a2713aSLionel Sambuc }
737f4a2713aSLionel Sambuc }
738f4a2713aSLionel Sambuc
hasValidSpacePrefix() const739f4a2713aSLionel Sambuc bool PrintfSpecifier::hasValidSpacePrefix() const {
740f4a2713aSLionel Sambuc if (!HasSpacePrefix)
741f4a2713aSLionel Sambuc return true;
742f4a2713aSLionel Sambuc
743f4a2713aSLionel Sambuc // The space prefix only makes sense for signed conversions
744f4a2713aSLionel Sambuc switch (CS.getKind()) {
745f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
746f4a2713aSLionel Sambuc case ConversionSpecifier::DArg:
747f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
748f4a2713aSLionel Sambuc case ConversionSpecifier::fArg:
749f4a2713aSLionel Sambuc case ConversionSpecifier::FArg:
750f4a2713aSLionel Sambuc case ConversionSpecifier::eArg:
751f4a2713aSLionel Sambuc case ConversionSpecifier::EArg:
752f4a2713aSLionel Sambuc case ConversionSpecifier::gArg:
753f4a2713aSLionel Sambuc case ConversionSpecifier::GArg:
754f4a2713aSLionel Sambuc case ConversionSpecifier::aArg:
755f4a2713aSLionel Sambuc case ConversionSpecifier::AArg:
756f4a2713aSLionel Sambuc return true;
757f4a2713aSLionel Sambuc
758f4a2713aSLionel Sambuc default:
759f4a2713aSLionel Sambuc return false;
760f4a2713aSLionel Sambuc }
761f4a2713aSLionel Sambuc }
762f4a2713aSLionel Sambuc
hasValidLeftJustified() const763f4a2713aSLionel Sambuc bool PrintfSpecifier::hasValidLeftJustified() const {
764f4a2713aSLionel Sambuc if (!IsLeftJustified)
765f4a2713aSLionel Sambuc return true;
766f4a2713aSLionel Sambuc
767f4a2713aSLionel Sambuc // The left justified flag is valid for all conversions except n
768f4a2713aSLionel Sambuc switch (CS.getKind()) {
769f4a2713aSLionel Sambuc case ConversionSpecifier::nArg:
770f4a2713aSLionel Sambuc return false;
771f4a2713aSLionel Sambuc
772f4a2713aSLionel Sambuc default:
773f4a2713aSLionel Sambuc return true;
774f4a2713aSLionel Sambuc }
775f4a2713aSLionel Sambuc }
776f4a2713aSLionel Sambuc
hasValidThousandsGroupingPrefix() const777f4a2713aSLionel Sambuc bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
778f4a2713aSLionel Sambuc if (!HasThousandsGrouping)
779f4a2713aSLionel Sambuc return true;
780f4a2713aSLionel Sambuc
781f4a2713aSLionel Sambuc switch (CS.getKind()) {
782f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
783f4a2713aSLionel Sambuc case ConversionSpecifier::DArg:
784f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
785f4a2713aSLionel Sambuc case ConversionSpecifier::uArg:
786f4a2713aSLionel Sambuc case ConversionSpecifier::UArg:
787f4a2713aSLionel Sambuc case ConversionSpecifier::fArg:
788f4a2713aSLionel Sambuc case ConversionSpecifier::FArg:
789f4a2713aSLionel Sambuc case ConversionSpecifier::gArg:
790f4a2713aSLionel Sambuc case ConversionSpecifier::GArg:
791f4a2713aSLionel Sambuc return true;
792f4a2713aSLionel Sambuc default:
793f4a2713aSLionel Sambuc return false;
794f4a2713aSLionel Sambuc }
795f4a2713aSLionel Sambuc }
796f4a2713aSLionel Sambuc
hasValidPrecision() const797f4a2713aSLionel Sambuc bool PrintfSpecifier::hasValidPrecision() const {
798f4a2713aSLionel Sambuc if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
799f4a2713aSLionel Sambuc return true;
800f4a2713aSLionel Sambuc
801f4a2713aSLionel Sambuc // Precision is only valid with the diouxXaAeEfFgGs conversions
802f4a2713aSLionel Sambuc switch (CS.getKind()) {
803f4a2713aSLionel Sambuc case ConversionSpecifier::dArg:
804f4a2713aSLionel Sambuc case ConversionSpecifier::DArg:
805f4a2713aSLionel Sambuc case ConversionSpecifier::iArg:
806f4a2713aSLionel Sambuc case ConversionSpecifier::oArg:
807f4a2713aSLionel Sambuc case ConversionSpecifier::OArg:
808f4a2713aSLionel Sambuc case ConversionSpecifier::uArg:
809f4a2713aSLionel Sambuc case ConversionSpecifier::UArg:
810f4a2713aSLionel Sambuc case ConversionSpecifier::xArg:
811f4a2713aSLionel Sambuc case ConversionSpecifier::XArg:
812f4a2713aSLionel Sambuc case ConversionSpecifier::aArg:
813f4a2713aSLionel Sambuc case ConversionSpecifier::AArg:
814f4a2713aSLionel Sambuc case ConversionSpecifier::eArg:
815f4a2713aSLionel Sambuc case ConversionSpecifier::EArg:
816f4a2713aSLionel Sambuc case ConversionSpecifier::fArg:
817f4a2713aSLionel Sambuc case ConversionSpecifier::FArg:
818f4a2713aSLionel Sambuc case ConversionSpecifier::gArg:
819f4a2713aSLionel Sambuc case ConversionSpecifier::GArg:
820f4a2713aSLionel Sambuc case ConversionSpecifier::sArg:
821f4a2713aSLionel Sambuc return true;
822f4a2713aSLionel Sambuc
823f4a2713aSLionel Sambuc default:
824f4a2713aSLionel Sambuc return false;
825f4a2713aSLionel Sambuc }
826f4a2713aSLionel Sambuc }
hasValidFieldWidth() const827f4a2713aSLionel Sambuc bool PrintfSpecifier::hasValidFieldWidth() const {
828f4a2713aSLionel Sambuc if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
829f4a2713aSLionel Sambuc return true;
830f4a2713aSLionel Sambuc
831f4a2713aSLionel Sambuc // The field width is valid for all conversions except n
832f4a2713aSLionel Sambuc switch (CS.getKind()) {
833f4a2713aSLionel Sambuc case ConversionSpecifier::nArg:
834f4a2713aSLionel Sambuc return false;
835f4a2713aSLionel Sambuc
836f4a2713aSLionel Sambuc default:
837f4a2713aSLionel Sambuc return true;
838f4a2713aSLionel Sambuc }
839f4a2713aSLionel Sambuc }
840