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