xref: /aosp_15_r20/external/clang/lib/Analysis/FormatString.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // FormatString.cpp - Common stuff for handling printf/scanf formats -*- 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 // Shared details for processing format strings of printf and scanf
11*67e74705SXin Li // (and friends).
12*67e74705SXin Li //
13*67e74705SXin Li //===----------------------------------------------------------------------===//
14*67e74705SXin Li 
15*67e74705SXin Li #include "FormatStringParsing.h"
16*67e74705SXin Li #include "clang/Basic/LangOptions.h"
17*67e74705SXin Li #include "clang/Basic/TargetInfo.h"
18*67e74705SXin Li #include "llvm/Support/ConvertUTF.h"
19*67e74705SXin Li 
20*67e74705SXin Li using clang::analyze_format_string::ArgType;
21*67e74705SXin Li using clang::analyze_format_string::FormatStringHandler;
22*67e74705SXin Li using clang::analyze_format_string::FormatSpecifier;
23*67e74705SXin Li using clang::analyze_format_string::LengthModifier;
24*67e74705SXin Li using clang::analyze_format_string::OptionalAmount;
25*67e74705SXin Li using clang::analyze_format_string::PositionContext;
26*67e74705SXin Li using clang::analyze_format_string::ConversionSpecifier;
27*67e74705SXin Li using namespace clang;
28*67e74705SXin Li 
29*67e74705SXin Li // Key function to FormatStringHandler.
~FormatStringHandler()30*67e74705SXin Li FormatStringHandler::~FormatStringHandler() {}
31*67e74705SXin Li 
32*67e74705SXin Li //===----------------------------------------------------------------------===//
33*67e74705SXin Li // Functions for parsing format strings components in both printf and
34*67e74705SXin Li // scanf format strings.
35*67e74705SXin Li //===----------------------------------------------------------------------===//
36*67e74705SXin Li 
37*67e74705SXin Li OptionalAmount
ParseAmount(const char * & Beg,const char * E)38*67e74705SXin Li clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {
39*67e74705SXin Li   const char *I = Beg;
40*67e74705SXin Li   UpdateOnReturn <const char*> UpdateBeg(Beg, I);
41*67e74705SXin Li 
42*67e74705SXin Li   unsigned accumulator = 0;
43*67e74705SXin Li   bool hasDigits = false;
44*67e74705SXin Li 
45*67e74705SXin Li   for ( ; I != E; ++I) {
46*67e74705SXin Li     char c = *I;
47*67e74705SXin Li     if (c >= '0' && c <= '9') {
48*67e74705SXin Li       hasDigits = true;
49*67e74705SXin Li       accumulator = (accumulator * 10) + (c - '0');
50*67e74705SXin Li       continue;
51*67e74705SXin Li     }
52*67e74705SXin Li 
53*67e74705SXin Li     if (hasDigits)
54*67e74705SXin Li       return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
55*67e74705SXin Li           false);
56*67e74705SXin Li 
57*67e74705SXin Li     break;
58*67e74705SXin Li   }
59*67e74705SXin Li 
60*67e74705SXin Li   return OptionalAmount();
61*67e74705SXin Li }
62*67e74705SXin Li 
63*67e74705SXin Li OptionalAmount
ParseNonPositionAmount(const char * & Beg,const char * E,unsigned & argIndex)64*67e74705SXin Li clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,
65*67e74705SXin Li                                                      const char *E,
66*67e74705SXin Li                                                      unsigned &argIndex) {
67*67e74705SXin Li   if (*Beg == '*') {
68*67e74705SXin Li     ++Beg;
69*67e74705SXin Li     return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
70*67e74705SXin Li   }
71*67e74705SXin Li 
72*67e74705SXin Li   return ParseAmount(Beg, E);
73*67e74705SXin Li }
74*67e74705SXin Li 
75*67e74705SXin Li OptionalAmount
ParsePositionAmount(FormatStringHandler & H,const char * Start,const char * & Beg,const char * E,PositionContext p)76*67e74705SXin Li clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,
77*67e74705SXin Li                                                   const char *Start,
78*67e74705SXin Li                                                   const char *&Beg,
79*67e74705SXin Li                                                   const char *E,
80*67e74705SXin Li                                                   PositionContext p) {
81*67e74705SXin Li   if (*Beg == '*') {
82*67e74705SXin Li     const char *I = Beg + 1;
83*67e74705SXin Li     const OptionalAmount &Amt = ParseAmount(I, E);
84*67e74705SXin Li 
85*67e74705SXin Li     if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
86*67e74705SXin Li       H.HandleInvalidPosition(Beg, I - Beg, p);
87*67e74705SXin Li       return OptionalAmount(false);
88*67e74705SXin Li     }
89*67e74705SXin Li 
90*67e74705SXin Li     if (I == E) {
91*67e74705SXin Li       // No more characters left?
92*67e74705SXin Li       H.HandleIncompleteSpecifier(Start, E - Start);
93*67e74705SXin Li       return OptionalAmount(false);
94*67e74705SXin Li     }
95*67e74705SXin Li 
96*67e74705SXin Li     assert(Amt.getHowSpecified() == OptionalAmount::Constant);
97*67e74705SXin Li 
98*67e74705SXin Li     if (*I == '$') {
99*67e74705SXin Li       // Handle positional arguments
100*67e74705SXin Li 
101*67e74705SXin Li       // Special case: '*0$', since this is an easy mistake.
102*67e74705SXin Li       if (Amt.getConstantAmount() == 0) {
103*67e74705SXin Li         H.HandleZeroPosition(Beg, I - Beg + 1);
104*67e74705SXin Li         return OptionalAmount(false);
105*67e74705SXin Li       }
106*67e74705SXin Li 
107*67e74705SXin Li       const char *Tmp = Beg;
108*67e74705SXin Li       Beg = ++I;
109*67e74705SXin Li 
110*67e74705SXin Li       return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
111*67e74705SXin Li                             Tmp, 0, true);
112*67e74705SXin Li     }
113*67e74705SXin Li 
114*67e74705SXin Li     H.HandleInvalidPosition(Beg, I - Beg, p);
115*67e74705SXin Li     return OptionalAmount(false);
116*67e74705SXin Li   }
117*67e74705SXin Li 
118*67e74705SXin Li   return ParseAmount(Beg, E);
119*67e74705SXin Li }
120*67e74705SXin Li 
121*67e74705SXin Li 
122*67e74705SXin Li bool
ParseFieldWidth(FormatStringHandler & H,FormatSpecifier & CS,const char * Start,const char * & Beg,const char * E,unsigned * argIndex)123*67e74705SXin Li clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,
124*67e74705SXin Li                                               FormatSpecifier &CS,
125*67e74705SXin Li                                               const char *Start,
126*67e74705SXin Li                                               const char *&Beg, const char *E,
127*67e74705SXin Li                                               unsigned *argIndex) {
128*67e74705SXin Li   // FIXME: Support negative field widths.
129*67e74705SXin Li   if (argIndex) {
130*67e74705SXin Li     CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
131*67e74705SXin Li   }
132*67e74705SXin Li   else {
133*67e74705SXin Li     const OptionalAmount Amt =
134*67e74705SXin Li       ParsePositionAmount(H, Start, Beg, E,
135*67e74705SXin Li                           analyze_format_string::FieldWidthPos);
136*67e74705SXin Li 
137*67e74705SXin Li     if (Amt.isInvalid())
138*67e74705SXin Li       return true;
139*67e74705SXin Li     CS.setFieldWidth(Amt);
140*67e74705SXin Li   }
141*67e74705SXin Li   return false;
142*67e74705SXin Li }
143*67e74705SXin Li 
144*67e74705SXin Li bool
ParseArgPosition(FormatStringHandler & H,FormatSpecifier & FS,const char * Start,const char * & Beg,const char * E)145*67e74705SXin Li clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
146*67e74705SXin Li                                                FormatSpecifier &FS,
147*67e74705SXin Li                                                const char *Start,
148*67e74705SXin Li                                                const char *&Beg,
149*67e74705SXin Li                                                const char *E) {
150*67e74705SXin Li   const char *I = Beg;
151*67e74705SXin Li 
152*67e74705SXin Li   const OptionalAmount &Amt = ParseAmount(I, E);
153*67e74705SXin Li 
154*67e74705SXin Li   if (I == E) {
155*67e74705SXin Li     // No more characters left?
156*67e74705SXin Li     H.HandleIncompleteSpecifier(Start, E - Start);
157*67e74705SXin Li     return true;
158*67e74705SXin Li   }
159*67e74705SXin Li 
160*67e74705SXin Li   if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
161*67e74705SXin Li     // Warn that positional arguments are non-standard.
162*67e74705SXin Li     H.HandlePosition(Start, I - Start);
163*67e74705SXin Li 
164*67e74705SXin Li     // Special case: '%0$', since this is an easy mistake.
165*67e74705SXin Li     if (Amt.getConstantAmount() == 0) {
166*67e74705SXin Li       H.HandleZeroPosition(Start, I - Start);
167*67e74705SXin Li       return true;
168*67e74705SXin Li     }
169*67e74705SXin Li 
170*67e74705SXin Li     FS.setArgIndex(Amt.getConstantAmount() - 1);
171*67e74705SXin Li     FS.setUsesPositionalArg();
172*67e74705SXin Li     // Update the caller's pointer if we decided to consume
173*67e74705SXin Li     // these characters.
174*67e74705SXin Li     Beg = I;
175*67e74705SXin Li     return false;
176*67e74705SXin Li   }
177*67e74705SXin Li 
178*67e74705SXin Li   return false;
179*67e74705SXin Li }
180*67e74705SXin Li 
181*67e74705SXin Li bool
ParseLengthModifier(FormatSpecifier & FS,const char * & I,const char * E,const LangOptions & LO,bool IsScanf)182*67e74705SXin Li clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
183*67e74705SXin Li                                                   const char *&I,
184*67e74705SXin Li                                                   const char *E,
185*67e74705SXin Li                                                   const LangOptions &LO,
186*67e74705SXin Li                                                   bool IsScanf) {
187*67e74705SXin Li   LengthModifier::Kind lmKind = LengthModifier::None;
188*67e74705SXin Li   const char *lmPosition = I;
189*67e74705SXin Li   switch (*I) {
190*67e74705SXin Li     default:
191*67e74705SXin Li       return false;
192*67e74705SXin Li     case 'h':
193*67e74705SXin Li       ++I;
194*67e74705SXin Li       if (I != E && *I == 'h') {
195*67e74705SXin Li         ++I;
196*67e74705SXin Li         lmKind = LengthModifier::AsChar;
197*67e74705SXin Li       } else {
198*67e74705SXin Li         lmKind = LengthModifier::AsShort;
199*67e74705SXin Li       }
200*67e74705SXin Li       break;
201*67e74705SXin Li     case 'l':
202*67e74705SXin Li       ++I;
203*67e74705SXin Li       if (I != E && *I == 'l') {
204*67e74705SXin Li         ++I;
205*67e74705SXin Li         lmKind = LengthModifier::AsLongLong;
206*67e74705SXin Li       } else {
207*67e74705SXin Li         lmKind = LengthModifier::AsLong;
208*67e74705SXin Li       }
209*67e74705SXin Li       break;
210*67e74705SXin Li     case 'j': lmKind = LengthModifier::AsIntMax;     ++I; break;
211*67e74705SXin Li     case 'z': lmKind = LengthModifier::AsSizeT;      ++I; break;
212*67e74705SXin Li     case 't': lmKind = LengthModifier::AsPtrDiff;    ++I; break;
213*67e74705SXin Li     case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
214*67e74705SXin Li     case 'q': lmKind = LengthModifier::AsQuad;       ++I; break;
215*67e74705SXin Li     case 'a':
216*67e74705SXin Li       if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
217*67e74705SXin Li         // For scanf in C90, look at the next character to see if this should
218*67e74705SXin Li         // be parsed as the GNU extension 'a' length modifier. If not, this
219*67e74705SXin Li         // will be parsed as a conversion specifier.
220*67e74705SXin Li         ++I;
221*67e74705SXin Li         if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
222*67e74705SXin Li           lmKind = LengthModifier::AsAllocate;
223*67e74705SXin Li           break;
224*67e74705SXin Li         }
225*67e74705SXin Li         --I;
226*67e74705SXin Li       }
227*67e74705SXin Li       return false;
228*67e74705SXin Li     case 'm':
229*67e74705SXin Li       if (IsScanf) {
230*67e74705SXin Li         lmKind = LengthModifier::AsMAllocate;
231*67e74705SXin Li         ++I;
232*67e74705SXin Li         break;
233*67e74705SXin Li       }
234*67e74705SXin Li       return false;
235*67e74705SXin Li     // printf: AsInt64, AsInt32, AsInt3264
236*67e74705SXin Li     // scanf:  AsInt64
237*67e74705SXin Li     case 'I':
238*67e74705SXin Li       if (I + 1 != E && I + 2 != E) {
239*67e74705SXin Li         if (I[1] == '6' && I[2] == '4') {
240*67e74705SXin Li           I += 3;
241*67e74705SXin Li           lmKind = LengthModifier::AsInt64;
242*67e74705SXin Li           break;
243*67e74705SXin Li         }
244*67e74705SXin Li         if (IsScanf)
245*67e74705SXin Li           return false;
246*67e74705SXin Li 
247*67e74705SXin Li         if (I[1] == '3' && I[2] == '2') {
248*67e74705SXin Li           I += 3;
249*67e74705SXin Li           lmKind = LengthModifier::AsInt32;
250*67e74705SXin Li           break;
251*67e74705SXin Li         }
252*67e74705SXin Li       }
253*67e74705SXin Li       ++I;
254*67e74705SXin Li       lmKind = LengthModifier::AsInt3264;
255*67e74705SXin Li       break;
256*67e74705SXin Li     case 'w':
257*67e74705SXin Li       lmKind = LengthModifier::AsWide; ++I; break;
258*67e74705SXin Li   }
259*67e74705SXin Li   LengthModifier lm(lmPosition, lmKind);
260*67e74705SXin Li   FS.setLengthModifier(lm);
261*67e74705SXin Li   return true;
262*67e74705SXin Li }
263*67e74705SXin Li 
ParseUTF8InvalidSpecifier(const char * SpecifierBegin,const char * FmtStrEnd,unsigned & Len)264*67e74705SXin Li bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(
265*67e74705SXin Li     const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {
266*67e74705SXin Li   if (SpecifierBegin + 1 >= FmtStrEnd)
267*67e74705SXin Li     return false;
268*67e74705SXin Li 
269*67e74705SXin Li   const UTF8 *SB = reinterpret_cast<const UTF8 *>(SpecifierBegin + 1);
270*67e74705SXin Li   const UTF8 *SE = reinterpret_cast<const UTF8 *>(FmtStrEnd);
271*67e74705SXin Li   const char FirstByte = *SB;
272*67e74705SXin Li 
273*67e74705SXin Li   // If the invalid specifier is a multibyte UTF-8 string, return the
274*67e74705SXin Li   // total length accordingly so that the conversion specifier can be
275*67e74705SXin Li   // properly updated to reflect a complete UTF-8 specifier.
276*67e74705SXin Li   unsigned NumBytes = getNumBytesForUTF8(FirstByte);
277*67e74705SXin Li   if (NumBytes == 1)
278*67e74705SXin Li     return false;
279*67e74705SXin Li   if (SB + NumBytes > SE)
280*67e74705SXin Li     return false;
281*67e74705SXin Li 
282*67e74705SXin Li   Len = NumBytes + 1;
283*67e74705SXin Li   return true;
284*67e74705SXin Li }
285*67e74705SXin Li 
286*67e74705SXin Li //===----------------------------------------------------------------------===//
287*67e74705SXin Li // Methods on ArgType.
288*67e74705SXin Li //===----------------------------------------------------------------------===//
289*67e74705SXin Li 
290*67e74705SXin Li clang::analyze_format_string::ArgType::MatchKind
matchesType(ASTContext & C,QualType argTy) const291*67e74705SXin Li ArgType::matchesType(ASTContext &C, QualType argTy) const {
292*67e74705SXin Li   if (Ptr) {
293*67e74705SXin Li     // It has to be a pointer.
294*67e74705SXin Li     const PointerType *PT = argTy->getAs<PointerType>();
295*67e74705SXin Li     if (!PT)
296*67e74705SXin Li       return NoMatch;
297*67e74705SXin Li 
298*67e74705SXin Li     // We cannot write through a const qualified pointer.
299*67e74705SXin Li     if (PT->getPointeeType().isConstQualified())
300*67e74705SXin Li       return NoMatch;
301*67e74705SXin Li 
302*67e74705SXin Li     argTy = PT->getPointeeType();
303*67e74705SXin Li   }
304*67e74705SXin Li 
305*67e74705SXin Li   switch (K) {
306*67e74705SXin Li     case InvalidTy:
307*67e74705SXin Li       llvm_unreachable("ArgType must be valid");
308*67e74705SXin Li 
309*67e74705SXin Li     case UnknownTy:
310*67e74705SXin Li       return Match;
311*67e74705SXin Li 
312*67e74705SXin Li     case AnyCharTy: {
313*67e74705SXin Li       if (const EnumType *ETy = argTy->getAs<EnumType>())
314*67e74705SXin Li         argTy = ETy->getDecl()->getIntegerType();
315*67e74705SXin Li 
316*67e74705SXin Li       if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
317*67e74705SXin Li         switch (BT->getKind()) {
318*67e74705SXin Li           default:
319*67e74705SXin Li             break;
320*67e74705SXin Li           case BuiltinType::Char_S:
321*67e74705SXin Li           case BuiltinType::SChar:
322*67e74705SXin Li           case BuiltinType::UChar:
323*67e74705SXin Li           case BuiltinType::Char_U:
324*67e74705SXin Li             return Match;
325*67e74705SXin Li         }
326*67e74705SXin Li       return NoMatch;
327*67e74705SXin Li     }
328*67e74705SXin Li 
329*67e74705SXin Li     case SpecificTy: {
330*67e74705SXin Li       if (const EnumType *ETy = argTy->getAs<EnumType>())
331*67e74705SXin Li         argTy = ETy->getDecl()->getIntegerType();
332*67e74705SXin Li       argTy = C.getCanonicalType(argTy).getUnqualifiedType();
333*67e74705SXin Li 
334*67e74705SXin Li       if (T == argTy)
335*67e74705SXin Li         return Match;
336*67e74705SXin Li       // Check for "compatible types".
337*67e74705SXin Li       if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
338*67e74705SXin Li         switch (BT->getKind()) {
339*67e74705SXin Li           default:
340*67e74705SXin Li             break;
341*67e74705SXin Li           case BuiltinType::Char_S:
342*67e74705SXin Li           case BuiltinType::SChar:
343*67e74705SXin Li           case BuiltinType::Char_U:
344*67e74705SXin Li           case BuiltinType::UChar:
345*67e74705SXin Li             return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match
346*67e74705SXin Li                                                                 : NoMatch;
347*67e74705SXin Li           case BuiltinType::Short:
348*67e74705SXin Li             return T == C.UnsignedShortTy ? Match : NoMatch;
349*67e74705SXin Li           case BuiltinType::UShort:
350*67e74705SXin Li             return T == C.ShortTy ? Match : NoMatch;
351*67e74705SXin Li           case BuiltinType::Int:
352*67e74705SXin Li             return T == C.UnsignedIntTy ? Match : NoMatch;
353*67e74705SXin Li           case BuiltinType::UInt:
354*67e74705SXin Li             return T == C.IntTy ? Match : NoMatch;
355*67e74705SXin Li           case BuiltinType::Long:
356*67e74705SXin Li             return T == C.UnsignedLongTy ? Match : NoMatch;
357*67e74705SXin Li           case BuiltinType::ULong:
358*67e74705SXin Li             return T == C.LongTy ? Match : NoMatch;
359*67e74705SXin Li           case BuiltinType::LongLong:
360*67e74705SXin Li             return T == C.UnsignedLongLongTy ? Match : NoMatch;
361*67e74705SXin Li           case BuiltinType::ULongLong:
362*67e74705SXin Li             return T == C.LongLongTy ? Match : NoMatch;
363*67e74705SXin Li         }
364*67e74705SXin Li       return NoMatch;
365*67e74705SXin Li     }
366*67e74705SXin Li 
367*67e74705SXin Li     case CStrTy: {
368*67e74705SXin Li       const PointerType *PT = argTy->getAs<PointerType>();
369*67e74705SXin Li       if (!PT)
370*67e74705SXin Li         return NoMatch;
371*67e74705SXin Li       QualType pointeeTy = PT->getPointeeType();
372*67e74705SXin Li       if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
373*67e74705SXin Li         switch (BT->getKind()) {
374*67e74705SXin Li           case BuiltinType::Void:
375*67e74705SXin Li           case BuiltinType::Char_U:
376*67e74705SXin Li           case BuiltinType::UChar:
377*67e74705SXin Li           case BuiltinType::Char_S:
378*67e74705SXin Li           case BuiltinType::SChar:
379*67e74705SXin Li             return Match;
380*67e74705SXin Li           default:
381*67e74705SXin Li             break;
382*67e74705SXin Li         }
383*67e74705SXin Li 
384*67e74705SXin Li       return NoMatch;
385*67e74705SXin Li     }
386*67e74705SXin Li 
387*67e74705SXin Li     case WCStrTy: {
388*67e74705SXin Li       const PointerType *PT = argTy->getAs<PointerType>();
389*67e74705SXin Li       if (!PT)
390*67e74705SXin Li         return NoMatch;
391*67e74705SXin Li       QualType pointeeTy =
392*67e74705SXin Li         C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
393*67e74705SXin Li       return pointeeTy == C.getWideCharType() ? Match : NoMatch;
394*67e74705SXin Li     }
395*67e74705SXin Li 
396*67e74705SXin Li     case WIntTy: {
397*67e74705SXin Li 
398*67e74705SXin Li       QualType PromoArg =
399*67e74705SXin Li         argTy->isPromotableIntegerType()
400*67e74705SXin Li           ? C.getPromotedIntegerType(argTy) : argTy;
401*67e74705SXin Li 
402*67e74705SXin Li       QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
403*67e74705SXin Li       PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
404*67e74705SXin Li 
405*67e74705SXin Li       // If the promoted argument is the corresponding signed type of the
406*67e74705SXin Li       // wint_t type, then it should match.
407*67e74705SXin Li       if (PromoArg->hasSignedIntegerRepresentation() &&
408*67e74705SXin Li           C.getCorrespondingUnsignedType(PromoArg) == WInt)
409*67e74705SXin Li         return Match;
410*67e74705SXin Li 
411*67e74705SXin Li       return WInt == PromoArg ? Match : NoMatch;
412*67e74705SXin Li     }
413*67e74705SXin Li 
414*67e74705SXin Li     case CPointerTy:
415*67e74705SXin Li       if (argTy->isVoidPointerType()) {
416*67e74705SXin Li         return Match;
417*67e74705SXin Li       } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
418*67e74705SXin Li             argTy->isBlockPointerType() || argTy->isNullPtrType()) {
419*67e74705SXin Li         return NoMatchPedantic;
420*67e74705SXin Li       } else {
421*67e74705SXin Li         return NoMatch;
422*67e74705SXin Li       }
423*67e74705SXin Li 
424*67e74705SXin Li     case ObjCPointerTy: {
425*67e74705SXin Li       if (argTy->getAs<ObjCObjectPointerType>() ||
426*67e74705SXin Li           argTy->getAs<BlockPointerType>())
427*67e74705SXin Li         return Match;
428*67e74705SXin Li 
429*67e74705SXin Li       // Handle implicit toll-free bridging.
430*67e74705SXin Li       if (const PointerType *PT = argTy->getAs<PointerType>()) {
431*67e74705SXin Li         // Things such as CFTypeRef are really just opaque pointers
432*67e74705SXin Li         // to C structs representing CF types that can often be bridged
433*67e74705SXin Li         // to Objective-C objects.  Since the compiler doesn't know which
434*67e74705SXin Li         // structs can be toll-free bridged, we just accept them all.
435*67e74705SXin Li         QualType pointee = PT->getPointeeType();
436*67e74705SXin Li         if (pointee->getAsStructureType() || pointee->isVoidType())
437*67e74705SXin Li           return Match;
438*67e74705SXin Li       }
439*67e74705SXin Li       return NoMatch;
440*67e74705SXin Li     }
441*67e74705SXin Li   }
442*67e74705SXin Li 
443*67e74705SXin Li   llvm_unreachable("Invalid ArgType Kind!");
444*67e74705SXin Li }
445*67e74705SXin Li 
getRepresentativeType(ASTContext & C) const446*67e74705SXin Li QualType ArgType::getRepresentativeType(ASTContext &C) const {
447*67e74705SXin Li   QualType Res;
448*67e74705SXin Li   switch (K) {
449*67e74705SXin Li     case InvalidTy:
450*67e74705SXin Li       llvm_unreachable("No representative type for Invalid ArgType");
451*67e74705SXin Li     case UnknownTy:
452*67e74705SXin Li       llvm_unreachable("No representative type for Unknown ArgType");
453*67e74705SXin Li     case AnyCharTy:
454*67e74705SXin Li       Res = C.CharTy;
455*67e74705SXin Li       break;
456*67e74705SXin Li     case SpecificTy:
457*67e74705SXin Li       Res = T;
458*67e74705SXin Li       break;
459*67e74705SXin Li     case CStrTy:
460*67e74705SXin Li       Res = C.getPointerType(C.CharTy);
461*67e74705SXin Li       break;
462*67e74705SXin Li     case WCStrTy:
463*67e74705SXin Li       Res = C.getPointerType(C.getWideCharType());
464*67e74705SXin Li       break;
465*67e74705SXin Li     case ObjCPointerTy:
466*67e74705SXin Li       Res = C.ObjCBuiltinIdTy;
467*67e74705SXin Li       break;
468*67e74705SXin Li     case CPointerTy:
469*67e74705SXin Li       Res = C.VoidPtrTy;
470*67e74705SXin Li       break;
471*67e74705SXin Li     case WIntTy: {
472*67e74705SXin Li       Res = C.getWIntType();
473*67e74705SXin Li       break;
474*67e74705SXin Li     }
475*67e74705SXin Li   }
476*67e74705SXin Li 
477*67e74705SXin Li   if (Ptr)
478*67e74705SXin Li     Res = C.getPointerType(Res);
479*67e74705SXin Li   return Res;
480*67e74705SXin Li }
481*67e74705SXin Li 
getRepresentativeTypeName(ASTContext & C) const482*67e74705SXin Li std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {
483*67e74705SXin Li   std::string S = getRepresentativeType(C).getAsString();
484*67e74705SXin Li 
485*67e74705SXin Li   std::string Alias;
486*67e74705SXin Li   if (Name) {
487*67e74705SXin Li     // Use a specific name for this type, e.g. "size_t".
488*67e74705SXin Li     Alias = Name;
489*67e74705SXin Li     if (Ptr) {
490*67e74705SXin Li       // If ArgType is actually a pointer to T, append an asterisk.
491*67e74705SXin Li       Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";
492*67e74705SXin Li     }
493*67e74705SXin Li     // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
494*67e74705SXin Li     if (S == Alias)
495*67e74705SXin Li       Alias.clear();
496*67e74705SXin Li   }
497*67e74705SXin Li 
498*67e74705SXin Li   if (!Alias.empty())
499*67e74705SXin Li     return std::string("'") + Alias + "' (aka '" + S + "')";
500*67e74705SXin Li   return std::string("'") + S + "'";
501*67e74705SXin Li }
502*67e74705SXin Li 
503*67e74705SXin Li 
504*67e74705SXin Li //===----------------------------------------------------------------------===//
505*67e74705SXin Li // Methods on OptionalAmount.
506*67e74705SXin Li //===----------------------------------------------------------------------===//
507*67e74705SXin Li 
508*67e74705SXin Li ArgType
getArgType(ASTContext & Ctx) const509*67e74705SXin Li analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {
510*67e74705SXin Li   return Ctx.IntTy;
511*67e74705SXin Li }
512*67e74705SXin Li 
513*67e74705SXin Li //===----------------------------------------------------------------------===//
514*67e74705SXin Li // Methods on LengthModifier.
515*67e74705SXin Li //===----------------------------------------------------------------------===//
516*67e74705SXin Li 
517*67e74705SXin Li const char *
toString() const518*67e74705SXin Li analyze_format_string::LengthModifier::toString() const {
519*67e74705SXin Li   switch (kind) {
520*67e74705SXin Li   case AsChar:
521*67e74705SXin Li     return "hh";
522*67e74705SXin Li   case AsShort:
523*67e74705SXin Li     return "h";
524*67e74705SXin Li   case AsLong: // or AsWideChar
525*67e74705SXin Li     return "l";
526*67e74705SXin Li   case AsLongLong:
527*67e74705SXin Li     return "ll";
528*67e74705SXin Li   case AsQuad:
529*67e74705SXin Li     return "q";
530*67e74705SXin Li   case AsIntMax:
531*67e74705SXin Li     return "j";
532*67e74705SXin Li   case AsSizeT:
533*67e74705SXin Li     return "z";
534*67e74705SXin Li   case AsPtrDiff:
535*67e74705SXin Li     return "t";
536*67e74705SXin Li   case AsInt32:
537*67e74705SXin Li     return "I32";
538*67e74705SXin Li   case AsInt3264:
539*67e74705SXin Li     return "I";
540*67e74705SXin Li   case AsInt64:
541*67e74705SXin Li     return "I64";
542*67e74705SXin Li   case AsLongDouble:
543*67e74705SXin Li     return "L";
544*67e74705SXin Li   case AsAllocate:
545*67e74705SXin Li     return "a";
546*67e74705SXin Li   case AsMAllocate:
547*67e74705SXin Li     return "m";
548*67e74705SXin Li   case AsWide:
549*67e74705SXin Li     return "w";
550*67e74705SXin Li   case None:
551*67e74705SXin Li     return "";
552*67e74705SXin Li   }
553*67e74705SXin Li   return nullptr;
554*67e74705SXin Li }
555*67e74705SXin Li 
556*67e74705SXin Li //===----------------------------------------------------------------------===//
557*67e74705SXin Li // Methods on ConversionSpecifier.
558*67e74705SXin Li //===----------------------------------------------------------------------===//
559*67e74705SXin Li 
toString() const560*67e74705SXin Li const char *ConversionSpecifier::toString() const {
561*67e74705SXin Li   switch (kind) {
562*67e74705SXin Li   case dArg: return "d";
563*67e74705SXin Li   case DArg: return "D";
564*67e74705SXin Li   case iArg: return "i";
565*67e74705SXin Li   case oArg: return "o";
566*67e74705SXin Li   case OArg: return "O";
567*67e74705SXin Li   case uArg: return "u";
568*67e74705SXin Li   case UArg: return "U";
569*67e74705SXin Li   case xArg: return "x";
570*67e74705SXin Li   case XArg: return "X";
571*67e74705SXin Li   case fArg: return "f";
572*67e74705SXin Li   case FArg: return "F";
573*67e74705SXin Li   case eArg: return "e";
574*67e74705SXin Li   case EArg: return "E";
575*67e74705SXin Li   case gArg: return "g";
576*67e74705SXin Li   case GArg: return "G";
577*67e74705SXin Li   case aArg: return "a";
578*67e74705SXin Li   case AArg: return "A";
579*67e74705SXin Li   case cArg: return "c";
580*67e74705SXin Li   case sArg: return "s";
581*67e74705SXin Li   case pArg: return "p";
582*67e74705SXin Li   case nArg: return "n";
583*67e74705SXin Li   case PercentArg:  return "%";
584*67e74705SXin Li   case ScanListArg: return "[";
585*67e74705SXin Li   case InvalidSpecifier: return nullptr;
586*67e74705SXin Li 
587*67e74705SXin Li   // POSIX unicode extensions.
588*67e74705SXin Li   case CArg: return "C";
589*67e74705SXin Li   case SArg: return "S";
590*67e74705SXin Li 
591*67e74705SXin Li   // Objective-C specific specifiers.
592*67e74705SXin Li   case ObjCObjArg: return "@";
593*67e74705SXin Li 
594*67e74705SXin Li   // FreeBSD kernel specific specifiers.
595*67e74705SXin Li   case FreeBSDbArg: return "b";
596*67e74705SXin Li   case FreeBSDDArg: return "D";
597*67e74705SXin Li   case FreeBSDrArg: return "r";
598*67e74705SXin Li   case FreeBSDyArg: return "y";
599*67e74705SXin Li 
600*67e74705SXin Li   // GlibC specific specifiers.
601*67e74705SXin Li   case PrintErrno: return "m";
602*67e74705SXin Li 
603*67e74705SXin Li   // MS specific specifiers.
604*67e74705SXin Li   case ZArg: return "Z";
605*67e74705SXin Li   }
606*67e74705SXin Li   return nullptr;
607*67e74705SXin Li }
608*67e74705SXin Li 
609*67e74705SXin Li Optional<ConversionSpecifier>
getStandardSpecifier() const610*67e74705SXin Li ConversionSpecifier::getStandardSpecifier() const {
611*67e74705SXin Li   ConversionSpecifier::Kind NewKind;
612*67e74705SXin Li 
613*67e74705SXin Li   switch (getKind()) {
614*67e74705SXin Li   default:
615*67e74705SXin Li     return None;
616*67e74705SXin Li   case DArg:
617*67e74705SXin Li     NewKind = dArg;
618*67e74705SXin Li     break;
619*67e74705SXin Li   case UArg:
620*67e74705SXin Li     NewKind = uArg;
621*67e74705SXin Li     break;
622*67e74705SXin Li   case OArg:
623*67e74705SXin Li     NewKind = oArg;
624*67e74705SXin Li     break;
625*67e74705SXin Li   }
626*67e74705SXin Li 
627*67e74705SXin Li   ConversionSpecifier FixedCS(*this);
628*67e74705SXin Li   FixedCS.setKind(NewKind);
629*67e74705SXin Li   return FixedCS;
630*67e74705SXin Li }
631*67e74705SXin Li 
632*67e74705SXin Li //===----------------------------------------------------------------------===//
633*67e74705SXin Li // Methods on OptionalAmount.
634*67e74705SXin Li //===----------------------------------------------------------------------===//
635*67e74705SXin Li 
toString(raw_ostream & os) const636*67e74705SXin Li void OptionalAmount::toString(raw_ostream &os) const {
637*67e74705SXin Li   switch (hs) {
638*67e74705SXin Li   case Invalid:
639*67e74705SXin Li   case NotSpecified:
640*67e74705SXin Li     return;
641*67e74705SXin Li   case Arg:
642*67e74705SXin Li     if (UsesDotPrefix)
643*67e74705SXin Li         os << ".";
644*67e74705SXin Li     if (usesPositionalArg())
645*67e74705SXin Li       os << "*" << getPositionalArgIndex() << "$";
646*67e74705SXin Li     else
647*67e74705SXin Li       os << "*";
648*67e74705SXin Li     break;
649*67e74705SXin Li   case Constant:
650*67e74705SXin Li     if (UsesDotPrefix)
651*67e74705SXin Li         os << ".";
652*67e74705SXin Li     os << amt;
653*67e74705SXin Li     break;
654*67e74705SXin Li   }
655*67e74705SXin Li }
656*67e74705SXin Li 
hasValidLengthModifier(const TargetInfo & Target) const657*67e74705SXin Li bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target) const {
658*67e74705SXin Li   switch (LM.getKind()) {
659*67e74705SXin Li     case LengthModifier::None:
660*67e74705SXin Li       return true;
661*67e74705SXin Li 
662*67e74705SXin Li     // Handle most integer flags
663*67e74705SXin Li     case LengthModifier::AsShort:
664*67e74705SXin Li       if (Target.getTriple().isOSMSVCRT()) {
665*67e74705SXin Li         switch (CS.getKind()) {
666*67e74705SXin Li           case ConversionSpecifier::cArg:
667*67e74705SXin Li           case ConversionSpecifier::CArg:
668*67e74705SXin Li           case ConversionSpecifier::sArg:
669*67e74705SXin Li           case ConversionSpecifier::SArg:
670*67e74705SXin Li           case ConversionSpecifier::ZArg:
671*67e74705SXin Li             return true;
672*67e74705SXin Li           default:
673*67e74705SXin Li             break;
674*67e74705SXin Li         }
675*67e74705SXin Li       }
676*67e74705SXin Li       // Fall through.
677*67e74705SXin Li     case LengthModifier::AsChar:
678*67e74705SXin Li     case LengthModifier::AsLongLong:
679*67e74705SXin Li     case LengthModifier::AsQuad:
680*67e74705SXin Li     case LengthModifier::AsIntMax:
681*67e74705SXin Li     case LengthModifier::AsSizeT:
682*67e74705SXin Li     case LengthModifier::AsPtrDiff:
683*67e74705SXin Li       switch (CS.getKind()) {
684*67e74705SXin Li         case ConversionSpecifier::dArg:
685*67e74705SXin Li         case ConversionSpecifier::DArg:
686*67e74705SXin Li         case ConversionSpecifier::iArg:
687*67e74705SXin Li         case ConversionSpecifier::oArg:
688*67e74705SXin Li         case ConversionSpecifier::OArg:
689*67e74705SXin Li         case ConversionSpecifier::uArg:
690*67e74705SXin Li         case ConversionSpecifier::UArg:
691*67e74705SXin Li         case ConversionSpecifier::xArg:
692*67e74705SXin Li         case ConversionSpecifier::XArg:
693*67e74705SXin Li         case ConversionSpecifier::nArg:
694*67e74705SXin Li           return true;
695*67e74705SXin Li         case ConversionSpecifier::FreeBSDrArg:
696*67e74705SXin Li         case ConversionSpecifier::FreeBSDyArg:
697*67e74705SXin Li           return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();
698*67e74705SXin Li         default:
699*67e74705SXin Li           return false;
700*67e74705SXin Li       }
701*67e74705SXin Li 
702*67e74705SXin Li     // Handle 'l' flag
703*67e74705SXin Li     case LengthModifier::AsLong: // or AsWideChar
704*67e74705SXin Li       switch (CS.getKind()) {
705*67e74705SXin Li         case ConversionSpecifier::dArg:
706*67e74705SXin Li         case ConversionSpecifier::DArg:
707*67e74705SXin Li         case ConversionSpecifier::iArg:
708*67e74705SXin Li         case ConversionSpecifier::oArg:
709*67e74705SXin Li         case ConversionSpecifier::OArg:
710*67e74705SXin Li         case ConversionSpecifier::uArg:
711*67e74705SXin Li         case ConversionSpecifier::UArg:
712*67e74705SXin Li         case ConversionSpecifier::xArg:
713*67e74705SXin Li         case ConversionSpecifier::XArg:
714*67e74705SXin Li         case ConversionSpecifier::aArg:
715*67e74705SXin Li         case ConversionSpecifier::AArg:
716*67e74705SXin Li         case ConversionSpecifier::fArg:
717*67e74705SXin Li         case ConversionSpecifier::FArg:
718*67e74705SXin Li         case ConversionSpecifier::eArg:
719*67e74705SXin Li         case ConversionSpecifier::EArg:
720*67e74705SXin Li         case ConversionSpecifier::gArg:
721*67e74705SXin Li         case ConversionSpecifier::GArg:
722*67e74705SXin Li         case ConversionSpecifier::nArg:
723*67e74705SXin Li         case ConversionSpecifier::cArg:
724*67e74705SXin Li         case ConversionSpecifier::sArg:
725*67e74705SXin Li         case ConversionSpecifier::ScanListArg:
726*67e74705SXin Li         case ConversionSpecifier::ZArg:
727*67e74705SXin Li           return true;
728*67e74705SXin Li         case ConversionSpecifier::FreeBSDrArg:
729*67e74705SXin Li         case ConversionSpecifier::FreeBSDyArg:
730*67e74705SXin Li           return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS4();
731*67e74705SXin Li         default:
732*67e74705SXin Li           return false;
733*67e74705SXin Li       }
734*67e74705SXin Li 
735*67e74705SXin Li     case LengthModifier::AsLongDouble:
736*67e74705SXin Li       switch (CS.getKind()) {
737*67e74705SXin Li         case ConversionSpecifier::aArg:
738*67e74705SXin Li         case ConversionSpecifier::AArg:
739*67e74705SXin Li         case ConversionSpecifier::fArg:
740*67e74705SXin Li         case ConversionSpecifier::FArg:
741*67e74705SXin Li         case ConversionSpecifier::eArg:
742*67e74705SXin Li         case ConversionSpecifier::EArg:
743*67e74705SXin Li         case ConversionSpecifier::gArg:
744*67e74705SXin Li         case ConversionSpecifier::GArg:
745*67e74705SXin Li           return true;
746*67e74705SXin Li         // GNU libc extension.
747*67e74705SXin Li         case ConversionSpecifier::dArg:
748*67e74705SXin Li         case ConversionSpecifier::iArg:
749*67e74705SXin Li         case ConversionSpecifier::oArg:
750*67e74705SXin Li         case ConversionSpecifier::uArg:
751*67e74705SXin Li         case ConversionSpecifier::xArg:
752*67e74705SXin Li         case ConversionSpecifier::XArg:
753*67e74705SXin Li           return !Target.getTriple().isOSDarwin() &&
754*67e74705SXin Li                  !Target.getTriple().isOSWindows();
755*67e74705SXin Li         default:
756*67e74705SXin Li           return false;
757*67e74705SXin Li       }
758*67e74705SXin Li 
759*67e74705SXin Li     case LengthModifier::AsAllocate:
760*67e74705SXin Li       switch (CS.getKind()) {
761*67e74705SXin Li         case ConversionSpecifier::sArg:
762*67e74705SXin Li         case ConversionSpecifier::SArg:
763*67e74705SXin Li         case ConversionSpecifier::ScanListArg:
764*67e74705SXin Li           return true;
765*67e74705SXin Li         default:
766*67e74705SXin Li           return false;
767*67e74705SXin Li       }
768*67e74705SXin Li 
769*67e74705SXin Li     case LengthModifier::AsMAllocate:
770*67e74705SXin Li       switch (CS.getKind()) {
771*67e74705SXin Li         case ConversionSpecifier::cArg:
772*67e74705SXin Li         case ConversionSpecifier::CArg:
773*67e74705SXin Li         case ConversionSpecifier::sArg:
774*67e74705SXin Li         case ConversionSpecifier::SArg:
775*67e74705SXin Li         case ConversionSpecifier::ScanListArg:
776*67e74705SXin Li           return true;
777*67e74705SXin Li         default:
778*67e74705SXin Li           return false;
779*67e74705SXin Li       }
780*67e74705SXin Li     case LengthModifier::AsInt32:
781*67e74705SXin Li     case LengthModifier::AsInt3264:
782*67e74705SXin Li     case LengthModifier::AsInt64:
783*67e74705SXin Li       switch (CS.getKind()) {
784*67e74705SXin Li         case ConversionSpecifier::dArg:
785*67e74705SXin Li         case ConversionSpecifier::iArg:
786*67e74705SXin Li         case ConversionSpecifier::oArg:
787*67e74705SXin Li         case ConversionSpecifier::uArg:
788*67e74705SXin Li         case ConversionSpecifier::xArg:
789*67e74705SXin Li         case ConversionSpecifier::XArg:
790*67e74705SXin Li           return Target.getTriple().isOSMSVCRT();
791*67e74705SXin Li         default:
792*67e74705SXin Li           return false;
793*67e74705SXin Li       }
794*67e74705SXin Li     case LengthModifier::AsWide:
795*67e74705SXin Li       switch (CS.getKind()) {
796*67e74705SXin Li         case ConversionSpecifier::cArg:
797*67e74705SXin Li         case ConversionSpecifier::CArg:
798*67e74705SXin Li         case ConversionSpecifier::sArg:
799*67e74705SXin Li         case ConversionSpecifier::SArg:
800*67e74705SXin Li         case ConversionSpecifier::ZArg:
801*67e74705SXin Li           return Target.getTriple().isOSMSVCRT();
802*67e74705SXin Li         default:
803*67e74705SXin Li           return false;
804*67e74705SXin Li       }
805*67e74705SXin Li   }
806*67e74705SXin Li   llvm_unreachable("Invalid LengthModifier Kind!");
807*67e74705SXin Li }
808*67e74705SXin Li 
hasStandardLengthModifier() const809*67e74705SXin Li bool FormatSpecifier::hasStandardLengthModifier() const {
810*67e74705SXin Li   switch (LM.getKind()) {
811*67e74705SXin Li     case LengthModifier::None:
812*67e74705SXin Li     case LengthModifier::AsChar:
813*67e74705SXin Li     case LengthModifier::AsShort:
814*67e74705SXin Li     case LengthModifier::AsLong:
815*67e74705SXin Li     case LengthModifier::AsLongLong:
816*67e74705SXin Li     case LengthModifier::AsIntMax:
817*67e74705SXin Li     case LengthModifier::AsSizeT:
818*67e74705SXin Li     case LengthModifier::AsPtrDiff:
819*67e74705SXin Li     case LengthModifier::AsLongDouble:
820*67e74705SXin Li       return true;
821*67e74705SXin Li     case LengthModifier::AsAllocate:
822*67e74705SXin Li     case LengthModifier::AsMAllocate:
823*67e74705SXin Li     case LengthModifier::AsQuad:
824*67e74705SXin Li     case LengthModifier::AsInt32:
825*67e74705SXin Li     case LengthModifier::AsInt3264:
826*67e74705SXin Li     case LengthModifier::AsInt64:
827*67e74705SXin Li     case LengthModifier::AsWide:
828*67e74705SXin Li       return false;
829*67e74705SXin Li   }
830*67e74705SXin Li   llvm_unreachable("Invalid LengthModifier Kind!");
831*67e74705SXin Li }
832*67e74705SXin Li 
hasStandardConversionSpecifier(const LangOptions & LangOpt) const833*67e74705SXin Li bool FormatSpecifier::hasStandardConversionSpecifier(
834*67e74705SXin Li     const LangOptions &LangOpt) const {
835*67e74705SXin Li   switch (CS.getKind()) {
836*67e74705SXin Li     case ConversionSpecifier::cArg:
837*67e74705SXin Li     case ConversionSpecifier::dArg:
838*67e74705SXin Li     case ConversionSpecifier::iArg:
839*67e74705SXin Li     case ConversionSpecifier::oArg:
840*67e74705SXin Li     case ConversionSpecifier::uArg:
841*67e74705SXin Li     case ConversionSpecifier::xArg:
842*67e74705SXin Li     case ConversionSpecifier::XArg:
843*67e74705SXin Li     case ConversionSpecifier::fArg:
844*67e74705SXin Li     case ConversionSpecifier::FArg:
845*67e74705SXin Li     case ConversionSpecifier::eArg:
846*67e74705SXin Li     case ConversionSpecifier::EArg:
847*67e74705SXin Li     case ConversionSpecifier::gArg:
848*67e74705SXin Li     case ConversionSpecifier::GArg:
849*67e74705SXin Li     case ConversionSpecifier::aArg:
850*67e74705SXin Li     case ConversionSpecifier::AArg:
851*67e74705SXin Li     case ConversionSpecifier::sArg:
852*67e74705SXin Li     case ConversionSpecifier::pArg:
853*67e74705SXin Li     case ConversionSpecifier::nArg:
854*67e74705SXin Li     case ConversionSpecifier::ObjCObjArg:
855*67e74705SXin Li     case ConversionSpecifier::ScanListArg:
856*67e74705SXin Li     case ConversionSpecifier::PercentArg:
857*67e74705SXin Li       return true;
858*67e74705SXin Li     case ConversionSpecifier::CArg:
859*67e74705SXin Li     case ConversionSpecifier::SArg:
860*67e74705SXin Li       return LangOpt.ObjC1 || LangOpt.ObjC2;
861*67e74705SXin Li     case ConversionSpecifier::InvalidSpecifier:
862*67e74705SXin Li     case ConversionSpecifier::FreeBSDbArg:
863*67e74705SXin Li     case ConversionSpecifier::FreeBSDDArg:
864*67e74705SXin Li     case ConversionSpecifier::FreeBSDrArg:
865*67e74705SXin Li     case ConversionSpecifier::FreeBSDyArg:
866*67e74705SXin Li     case ConversionSpecifier::PrintErrno:
867*67e74705SXin Li     case ConversionSpecifier::DArg:
868*67e74705SXin Li     case ConversionSpecifier::OArg:
869*67e74705SXin Li     case ConversionSpecifier::UArg:
870*67e74705SXin Li     case ConversionSpecifier::ZArg:
871*67e74705SXin Li       return false;
872*67e74705SXin Li   }
873*67e74705SXin Li   llvm_unreachable("Invalid ConversionSpecifier Kind!");
874*67e74705SXin Li }
875*67e74705SXin Li 
hasStandardLengthConversionCombination() const876*67e74705SXin Li bool FormatSpecifier::hasStandardLengthConversionCombination() const {
877*67e74705SXin Li   if (LM.getKind() == LengthModifier::AsLongDouble) {
878*67e74705SXin Li     switch(CS.getKind()) {
879*67e74705SXin Li         case ConversionSpecifier::dArg:
880*67e74705SXin Li         case ConversionSpecifier::iArg:
881*67e74705SXin Li         case ConversionSpecifier::oArg:
882*67e74705SXin Li         case ConversionSpecifier::uArg:
883*67e74705SXin Li         case ConversionSpecifier::xArg:
884*67e74705SXin Li         case ConversionSpecifier::XArg:
885*67e74705SXin Li           return false;
886*67e74705SXin Li         default:
887*67e74705SXin Li           return true;
888*67e74705SXin Li     }
889*67e74705SXin Li   }
890*67e74705SXin Li   return true;
891*67e74705SXin Li }
892*67e74705SXin Li 
getCorrectedLengthModifier() const893*67e74705SXin Li Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const {
894*67e74705SXin Li   if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
895*67e74705SXin Li     if (LM.getKind() == LengthModifier::AsLongDouble ||
896*67e74705SXin Li         LM.getKind() == LengthModifier::AsQuad) {
897*67e74705SXin Li       LengthModifier FixedLM(LM);
898*67e74705SXin Li       FixedLM.setKind(LengthModifier::AsLongLong);
899*67e74705SXin Li       return FixedLM;
900*67e74705SXin Li     }
901*67e74705SXin Li   }
902*67e74705SXin Li 
903*67e74705SXin Li   return None;
904*67e74705SXin Li }
905*67e74705SXin Li 
namedTypeToLengthModifier(QualType QT,LengthModifier & LM)906*67e74705SXin Li bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,
907*67e74705SXin Li                                                 LengthModifier &LM) {
908*67e74705SXin Li   assert(isa<TypedefType>(QT) && "Expected a TypedefType");
909*67e74705SXin Li   const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();
910*67e74705SXin Li 
911*67e74705SXin Li   for (;;) {
912*67e74705SXin Li     const IdentifierInfo *Identifier = Typedef->getIdentifier();
913*67e74705SXin Li     if (Identifier->getName() == "size_t") {
914*67e74705SXin Li       LM.setKind(LengthModifier::AsSizeT);
915*67e74705SXin Li       return true;
916*67e74705SXin Li     } else if (Identifier->getName() == "ssize_t") {
917*67e74705SXin Li       // Not C99, but common in Unix.
918*67e74705SXin Li       LM.setKind(LengthModifier::AsSizeT);
919*67e74705SXin Li       return true;
920*67e74705SXin Li     } else if (Identifier->getName() == "intmax_t") {
921*67e74705SXin Li       LM.setKind(LengthModifier::AsIntMax);
922*67e74705SXin Li       return true;
923*67e74705SXin Li     } else if (Identifier->getName() == "uintmax_t") {
924*67e74705SXin Li       LM.setKind(LengthModifier::AsIntMax);
925*67e74705SXin Li       return true;
926*67e74705SXin Li     } else if (Identifier->getName() == "ptrdiff_t") {
927*67e74705SXin Li       LM.setKind(LengthModifier::AsPtrDiff);
928*67e74705SXin Li       return true;
929*67e74705SXin Li     }
930*67e74705SXin Li 
931*67e74705SXin Li     QualType T = Typedef->getUnderlyingType();
932*67e74705SXin Li     if (!isa<TypedefType>(T))
933*67e74705SXin Li       break;
934*67e74705SXin Li 
935*67e74705SXin Li     Typedef = cast<TypedefType>(T)->getDecl();
936*67e74705SXin Li   }
937*67e74705SXin Li   return false;
938*67e74705SXin Li }
939