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