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