1314fbfa1STim Northover // FormatString.cpp - Common stuff for handling printf/scanf formats -*- C++ -*-
2314fbfa1STim Northover //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6314fbfa1STim Northover //
7314fbfa1STim Northover //===----------------------------------------------------------------------===//
8314fbfa1STim Northover //
9314fbfa1STim Northover // Shared details for processing format strings of printf and scanf
10314fbfa1STim Northover // (and friends).
11314fbfa1STim Northover //
12314fbfa1STim Northover //===----------------------------------------------------------------------===//
13314fbfa1STim Northover 
14314fbfa1STim Northover #include "FormatStringParsing.h"
15314fbfa1STim Northover #include "clang/Basic/LangOptions.h"
16314fbfa1STim Northover #include "clang/Basic/TargetInfo.h"
17314fbfa1STim Northover #include "llvm/Support/ConvertUTF.h"
18314fbfa1STim Northover 
19314fbfa1STim Northover using clang::analyze_format_string::ArgType;
20314fbfa1STim Northover using clang::analyze_format_string::FormatStringHandler;
21314fbfa1STim Northover using clang::analyze_format_string::FormatSpecifier;
22314fbfa1STim Northover using clang::analyze_format_string::LengthModifier;
23314fbfa1STim Northover using clang::analyze_format_string::OptionalAmount;
24314fbfa1STim Northover using clang::analyze_format_string::ConversionSpecifier;
25314fbfa1STim Northover using namespace clang;
26314fbfa1STim Northover 
27314fbfa1STim Northover // Key function to FormatStringHandler.
~FormatStringHandler()28314fbfa1STim Northover FormatStringHandler::~FormatStringHandler() {}
29314fbfa1STim Northover 
30314fbfa1STim Northover //===----------------------------------------------------------------------===//
31314fbfa1STim Northover // Functions for parsing format strings components in both printf and
32314fbfa1STim Northover // scanf format strings.
33314fbfa1STim Northover //===----------------------------------------------------------------------===//
34314fbfa1STim Northover 
35314fbfa1STim Northover OptionalAmount
ParseAmount(const char * & Beg,const char * E)36314fbfa1STim Northover clang::analyze_format_string::ParseAmount(const char *&Beg, const char *E) {
37314fbfa1STim Northover   const char *I = Beg;
38314fbfa1STim Northover   UpdateOnReturn <const char*> UpdateBeg(Beg, I);
39314fbfa1STim Northover 
40314fbfa1STim Northover   unsigned accumulator = 0;
41314fbfa1STim Northover   bool hasDigits = false;
42314fbfa1STim Northover 
43314fbfa1STim Northover   for ( ; I != E; ++I) {
44314fbfa1STim Northover     char c = *I;
45314fbfa1STim Northover     if (c >= '0' && c <= '9') {
46314fbfa1STim Northover       hasDigits = true;
47314fbfa1STim Northover       accumulator = (accumulator * 10) + (c - '0');
48314fbfa1STim Northover       continue;
49314fbfa1STim Northover     }
50314fbfa1STim Northover 
51314fbfa1STim Northover     if (hasDigits)
52314fbfa1STim Northover       return OptionalAmount(OptionalAmount::Constant, accumulator, Beg, I - Beg,
53314fbfa1STim Northover           false);
54314fbfa1STim Northover 
55314fbfa1STim Northover     break;
56314fbfa1STim Northover   }
57314fbfa1STim Northover 
58314fbfa1STim Northover   return OptionalAmount();
59314fbfa1STim Northover }
60314fbfa1STim Northover 
61314fbfa1STim Northover OptionalAmount
ParseNonPositionAmount(const char * & Beg,const char * E,unsigned & argIndex)62314fbfa1STim Northover clang::analyze_format_string::ParseNonPositionAmount(const char *&Beg,
63314fbfa1STim Northover                                                      const char *E,
64314fbfa1STim Northover                                                      unsigned &argIndex) {
65314fbfa1STim Northover   if (*Beg == '*') {
66314fbfa1STim Northover     ++Beg;
67314fbfa1STim Northover     return OptionalAmount(OptionalAmount::Arg, argIndex++, Beg, 0, false);
68314fbfa1STim Northover   }
69314fbfa1STim Northover 
70314fbfa1STim Northover   return ParseAmount(Beg, E);
71314fbfa1STim Northover }
72314fbfa1STim Northover 
73314fbfa1STim Northover OptionalAmount
ParsePositionAmount(FormatStringHandler & H,const char * Start,const char * & Beg,const char * E,PositionContext p)74314fbfa1STim Northover clang::analyze_format_string::ParsePositionAmount(FormatStringHandler &H,
75314fbfa1STim Northover                                                   const char *Start,
76314fbfa1STim Northover                                                   const char *&Beg,
77314fbfa1STim Northover                                                   const char *E,
78314fbfa1STim Northover                                                   PositionContext p) {
79314fbfa1STim Northover   if (*Beg == '*') {
80314fbfa1STim Northover     const char *I = Beg + 1;
81314fbfa1STim Northover     const OptionalAmount &Amt = ParseAmount(I, E);
82314fbfa1STim Northover 
83314fbfa1STim Northover     if (Amt.getHowSpecified() == OptionalAmount::NotSpecified) {
84314fbfa1STim Northover       H.HandleInvalidPosition(Beg, I - Beg, p);
85314fbfa1STim Northover       return OptionalAmount(false);
86314fbfa1STim Northover     }
87314fbfa1STim Northover 
88314fbfa1STim Northover     if (I == E) {
89314fbfa1STim Northover       // No more characters left?
90314fbfa1STim Northover       H.HandleIncompleteSpecifier(Start, E - Start);
91314fbfa1STim Northover       return OptionalAmount(false);
92314fbfa1STim Northover     }
93314fbfa1STim Northover 
94314fbfa1STim Northover     assert(Amt.getHowSpecified() == OptionalAmount::Constant);
95314fbfa1STim Northover 
96314fbfa1STim Northover     if (*I == '$') {
97314fbfa1STim Northover       // Handle positional arguments
98314fbfa1STim Northover 
99314fbfa1STim Northover       // Special case: '*0$', since this is an easy mistake.
100314fbfa1STim Northover       if (Amt.getConstantAmount() == 0) {
101314fbfa1STim Northover         H.HandleZeroPosition(Beg, I - Beg + 1);
102314fbfa1STim Northover         return OptionalAmount(false);
103314fbfa1STim Northover       }
104314fbfa1STim Northover 
105314fbfa1STim Northover       const char *Tmp = Beg;
106314fbfa1STim Northover       Beg = ++I;
107314fbfa1STim Northover 
108314fbfa1STim Northover       return OptionalAmount(OptionalAmount::Arg, Amt.getConstantAmount() - 1,
109314fbfa1STim Northover                             Tmp, 0, true);
110314fbfa1STim Northover     }
111314fbfa1STim Northover 
112314fbfa1STim Northover     H.HandleInvalidPosition(Beg, I - Beg, p);
113314fbfa1STim Northover     return OptionalAmount(false);
114314fbfa1STim Northover   }
115314fbfa1STim Northover 
116314fbfa1STim Northover   return ParseAmount(Beg, E);
117314fbfa1STim Northover }
118314fbfa1STim Northover 
119314fbfa1STim Northover 
120314fbfa1STim Northover bool
ParseFieldWidth(FormatStringHandler & H,FormatSpecifier & CS,const char * Start,const char * & Beg,const char * E,unsigned * argIndex)121314fbfa1STim Northover clang::analyze_format_string::ParseFieldWidth(FormatStringHandler &H,
122314fbfa1STim Northover                                               FormatSpecifier &CS,
123314fbfa1STim Northover                                               const char *Start,
124314fbfa1STim Northover                                               const char *&Beg, const char *E,
125314fbfa1STim Northover                                               unsigned *argIndex) {
126314fbfa1STim Northover   // FIXME: Support negative field widths.
127314fbfa1STim Northover   if (argIndex) {
128314fbfa1STim Northover     CS.setFieldWidth(ParseNonPositionAmount(Beg, E, *argIndex));
129314fbfa1STim Northover   }
130314fbfa1STim Northover   else {
131314fbfa1STim Northover     const OptionalAmount Amt =
132314fbfa1STim Northover       ParsePositionAmount(H, Start, Beg, E,
133314fbfa1STim Northover                           analyze_format_string::FieldWidthPos);
134314fbfa1STim Northover 
135314fbfa1STim Northover     if (Amt.isInvalid())
136314fbfa1STim Northover       return true;
137314fbfa1STim Northover     CS.setFieldWidth(Amt);
138314fbfa1STim Northover   }
139314fbfa1STim Northover   return false;
140314fbfa1STim Northover }
141314fbfa1STim Northover 
142314fbfa1STim Northover bool
ParseArgPosition(FormatStringHandler & H,FormatSpecifier & FS,const char * Start,const char * & Beg,const char * E)143314fbfa1STim Northover clang::analyze_format_string::ParseArgPosition(FormatStringHandler &H,
144314fbfa1STim Northover                                                FormatSpecifier &FS,
145314fbfa1STim Northover                                                const char *Start,
146314fbfa1STim Northover                                                const char *&Beg,
147314fbfa1STim Northover                                                const char *E) {
148314fbfa1STim Northover   const char *I = Beg;
149314fbfa1STim Northover 
150314fbfa1STim Northover   const OptionalAmount &Amt = ParseAmount(I, E);
151314fbfa1STim Northover 
152314fbfa1STim Northover   if (I == E) {
153314fbfa1STim Northover     // No more characters left?
154314fbfa1STim Northover     H.HandleIncompleteSpecifier(Start, E - Start);
155314fbfa1STim Northover     return true;
156314fbfa1STim Northover   }
157314fbfa1STim Northover 
158314fbfa1STim Northover   if (Amt.getHowSpecified() == OptionalAmount::Constant && *(I++) == '$') {
159314fbfa1STim Northover     // Warn that positional arguments are non-standard.
160314fbfa1STim Northover     H.HandlePosition(Start, I - Start);
161314fbfa1STim Northover 
162314fbfa1STim Northover     // Special case: '%0$', since this is an easy mistake.
163314fbfa1STim Northover     if (Amt.getConstantAmount() == 0) {
164314fbfa1STim Northover       H.HandleZeroPosition(Start, I - Start);
165314fbfa1STim Northover       return true;
166314fbfa1STim Northover     }
167314fbfa1STim Northover 
168314fbfa1STim Northover     FS.setArgIndex(Amt.getConstantAmount() - 1);
169314fbfa1STim Northover     FS.setUsesPositionalArg();
170314fbfa1STim Northover     // Update the caller's pointer if we decided to consume
171314fbfa1STim Northover     // these characters.
172314fbfa1STim Northover     Beg = I;
173314fbfa1STim Northover     return false;
174314fbfa1STim Northover   }
175314fbfa1STim Northover 
176314fbfa1STim Northover   return false;
177314fbfa1STim Northover }
178314fbfa1STim Northover 
179314fbfa1STim Northover bool
ParseVectorModifier(FormatStringHandler & H,FormatSpecifier & FS,const char * & I,const char * E,const LangOptions & LO)1800ff50d49SMatt Arsenault clang::analyze_format_string::ParseVectorModifier(FormatStringHandler &H,
1810ff50d49SMatt Arsenault                                                   FormatSpecifier &FS,
1820ff50d49SMatt Arsenault                                                   const char *&I,
1830ff50d49SMatt Arsenault                                                   const char *E,
1840ff50d49SMatt Arsenault                                                   const LangOptions &LO) {
1850ff50d49SMatt Arsenault   if (!LO.OpenCL)
1860ff50d49SMatt Arsenault     return false;
1870ff50d49SMatt Arsenault 
1880ff50d49SMatt Arsenault   const char *Start = I;
1890ff50d49SMatt Arsenault   if (*I == 'v') {
1900ff50d49SMatt Arsenault     ++I;
1910ff50d49SMatt Arsenault 
1920ff50d49SMatt Arsenault     if (I == E) {
1930ff50d49SMatt Arsenault       H.HandleIncompleteSpecifier(Start, E - Start);
1940ff50d49SMatt Arsenault       return true;
1950ff50d49SMatt Arsenault     }
1960ff50d49SMatt Arsenault 
1970ff50d49SMatt Arsenault     OptionalAmount NumElts = ParseAmount(I, E);
1980ff50d49SMatt Arsenault     if (NumElts.getHowSpecified() != OptionalAmount::Constant) {
1990ff50d49SMatt Arsenault       H.HandleIncompleteSpecifier(Start, E - Start);
2000ff50d49SMatt Arsenault       return true;
2010ff50d49SMatt Arsenault     }
2020ff50d49SMatt Arsenault 
2030ff50d49SMatt Arsenault     FS.setVectorNumElts(NumElts);
2040ff50d49SMatt Arsenault   }
2050ff50d49SMatt Arsenault 
2060ff50d49SMatt Arsenault   return false;
2070ff50d49SMatt Arsenault }
2080ff50d49SMatt Arsenault 
2090ff50d49SMatt Arsenault bool
ParseLengthModifier(FormatSpecifier & FS,const char * & I,const char * E,const LangOptions & LO,bool IsScanf)210314fbfa1STim Northover clang::analyze_format_string::ParseLengthModifier(FormatSpecifier &FS,
211314fbfa1STim Northover                                                   const char *&I,
212314fbfa1STim Northover                                                   const char *E,
213314fbfa1STim Northover                                                   const LangOptions &LO,
214314fbfa1STim Northover                                                   bool IsScanf) {
215314fbfa1STim Northover   LengthModifier::Kind lmKind = LengthModifier::None;
216314fbfa1STim Northover   const char *lmPosition = I;
217314fbfa1STim Northover   switch (*I) {
218314fbfa1STim Northover     default:
219314fbfa1STim Northover       return false;
220314fbfa1STim Northover     case 'h':
221314fbfa1STim Northover       ++I;
222314fbfa1STim Northover       if (I != E && *I == 'h') {
223314fbfa1STim Northover         ++I;
224314fbfa1STim Northover         lmKind = LengthModifier::AsChar;
22558fc8082SMatt Arsenault       } else if (I != E && *I == 'l' && LO.OpenCL) {
22658fc8082SMatt Arsenault         ++I;
22758fc8082SMatt Arsenault         lmKind = LengthModifier::AsShortLong;
228314fbfa1STim Northover       } else {
229314fbfa1STim Northover         lmKind = LengthModifier::AsShort;
230314fbfa1STim Northover       }
231314fbfa1STim Northover       break;
232314fbfa1STim Northover     case 'l':
233314fbfa1STim Northover       ++I;
234314fbfa1STim Northover       if (I != E && *I == 'l') {
235314fbfa1STim Northover         ++I;
236314fbfa1STim Northover         lmKind = LengthModifier::AsLongLong;
237314fbfa1STim Northover       } else {
238314fbfa1STim Northover         lmKind = LengthModifier::AsLong;
239314fbfa1STim Northover       }
240314fbfa1STim Northover       break;
241314fbfa1STim Northover     case 'j': lmKind = LengthModifier::AsIntMax;     ++I; break;
242314fbfa1STim Northover     case 'z': lmKind = LengthModifier::AsSizeT;      ++I; break;
243314fbfa1STim Northover     case 't': lmKind = LengthModifier::AsPtrDiff;    ++I; break;
244314fbfa1STim Northover     case 'L': lmKind = LengthModifier::AsLongDouble; ++I; break;
245314fbfa1STim Northover     case 'q': lmKind = LengthModifier::AsQuad;       ++I; break;
246314fbfa1STim Northover     case 'a':
247314fbfa1STim Northover       if (IsScanf && !LO.C99 && !LO.CPlusPlus11) {
248314fbfa1STim Northover         // For scanf in C90, look at the next character to see if this should
249314fbfa1STim Northover         // be parsed as the GNU extension 'a' length modifier. If not, this
250314fbfa1STim Northover         // will be parsed as a conversion specifier.
251314fbfa1STim Northover         ++I;
252314fbfa1STim Northover         if (I != E && (*I == 's' || *I == 'S' || *I == '[')) {
253314fbfa1STim Northover           lmKind = LengthModifier::AsAllocate;
254314fbfa1STim Northover           break;
255314fbfa1STim Northover         }
256314fbfa1STim Northover         --I;
257314fbfa1STim Northover       }
258314fbfa1STim Northover       return false;
259314fbfa1STim Northover     case 'm':
260314fbfa1STim Northover       if (IsScanf) {
261314fbfa1STim Northover         lmKind = LengthModifier::AsMAllocate;
262314fbfa1STim Northover         ++I;
263314fbfa1STim Northover         break;
264314fbfa1STim Northover       }
265314fbfa1STim Northover       return false;
266314fbfa1STim Northover     // printf: AsInt64, AsInt32, AsInt3264
267314fbfa1STim Northover     // scanf:  AsInt64
268314fbfa1STim Northover     case 'I':
269314fbfa1STim Northover       if (I + 1 != E && I + 2 != E) {
270314fbfa1STim Northover         if (I[1] == '6' && I[2] == '4') {
271314fbfa1STim Northover           I += 3;
272314fbfa1STim Northover           lmKind = LengthModifier::AsInt64;
273314fbfa1STim Northover           break;
274314fbfa1STim Northover         }
275314fbfa1STim Northover         if (IsScanf)
276314fbfa1STim Northover           return false;
277314fbfa1STim Northover 
278314fbfa1STim Northover         if (I[1] == '3' && I[2] == '2') {
279314fbfa1STim Northover           I += 3;
280314fbfa1STim Northover           lmKind = LengthModifier::AsInt32;
281314fbfa1STim Northover           break;
282314fbfa1STim Northover         }
283314fbfa1STim Northover       }
284314fbfa1STim Northover       ++I;
285314fbfa1STim Northover       lmKind = LengthModifier::AsInt3264;
286314fbfa1STim Northover       break;
287314fbfa1STim Northover     case 'w':
288314fbfa1STim Northover       lmKind = LengthModifier::AsWide; ++I; break;
289314fbfa1STim Northover   }
290314fbfa1STim Northover   LengthModifier lm(lmPosition, lmKind);
291314fbfa1STim Northover   FS.setLengthModifier(lm);
292314fbfa1STim Northover   return true;
293314fbfa1STim Northover }
294314fbfa1STim Northover 
ParseUTF8InvalidSpecifier(const char * SpecifierBegin,const char * FmtStrEnd,unsigned & Len)295314fbfa1STim Northover bool clang::analyze_format_string::ParseUTF8InvalidSpecifier(
296314fbfa1STim Northover     const char *SpecifierBegin, const char *FmtStrEnd, unsigned &Len) {
297314fbfa1STim Northover   if (SpecifierBegin + 1 >= FmtStrEnd)
298314fbfa1STim Northover     return false;
299314fbfa1STim Northover 
300314fbfa1STim Northover   const llvm::UTF8 *SB =
301314fbfa1STim Northover       reinterpret_cast<const llvm::UTF8 *>(SpecifierBegin + 1);
302314fbfa1STim Northover   const llvm::UTF8 *SE = reinterpret_cast<const llvm::UTF8 *>(FmtStrEnd);
303314fbfa1STim Northover   const char FirstByte = *SB;
304314fbfa1STim Northover 
305314fbfa1STim Northover   // If the invalid specifier is a multibyte UTF-8 string, return the
306314fbfa1STim Northover   // total length accordingly so that the conversion specifier can be
307314fbfa1STim Northover   // properly updated to reflect a complete UTF-8 specifier.
308314fbfa1STim Northover   unsigned NumBytes = llvm::getNumBytesForUTF8(FirstByte);
309314fbfa1STim Northover   if (NumBytes == 1)
310314fbfa1STim Northover     return false;
311314fbfa1STim Northover   if (SB + NumBytes > SE)
312314fbfa1STim Northover     return false;
313314fbfa1STim Northover 
314314fbfa1STim Northover   Len = NumBytes + 1;
315314fbfa1STim Northover   return true;
316314fbfa1STim Northover }
317314fbfa1STim Northover 
318314fbfa1STim Northover //===----------------------------------------------------------------------===//
319314fbfa1STim Northover // Methods on ArgType.
320314fbfa1STim Northover //===----------------------------------------------------------------------===//
321314fbfa1STim Northover 
322314fbfa1STim Northover clang::analyze_format_string::ArgType::MatchKind
matchesType(ASTContext & C,QualType argTy) const323314fbfa1STim Northover ArgType::matchesType(ASTContext &C, QualType argTy) const {
32492edd74bSFélix Cloutier   // When using the format attribute in C++, you can receive a function or an
32592edd74bSFélix Cloutier   // array that will necessarily decay to a pointer when passed to the final
32692edd74bSFélix Cloutier   // format consumer. Apply decay before type comparison.
32792edd74bSFélix Cloutier   if (argTy->canDecayToPointerType())
32892edd74bSFélix Cloutier     argTy = C.getDecayedType(argTy);
32992edd74bSFélix Cloutier 
330314fbfa1STim Northover   if (Ptr) {
331314fbfa1STim Northover     // It has to be a pointer.
332314fbfa1STim Northover     const PointerType *PT = argTy->getAs<PointerType>();
333314fbfa1STim Northover     if (!PT)
334314fbfa1STim Northover       return NoMatch;
335314fbfa1STim Northover 
336314fbfa1STim Northover     // We cannot write through a const qualified pointer.
337314fbfa1STim Northover     if (PT->getPointeeType().isConstQualified())
338314fbfa1STim Northover       return NoMatch;
339314fbfa1STim Northover 
340314fbfa1STim Northover     argTy = PT->getPointeeType();
341314fbfa1STim Northover   }
342314fbfa1STim Northover 
343314fbfa1STim Northover   switch (K) {
344314fbfa1STim Northover     case InvalidTy:
345314fbfa1STim Northover       llvm_unreachable("ArgType must be valid");
346314fbfa1STim Northover 
347314fbfa1STim Northover     case UnknownTy:
348314fbfa1STim Northover       return Match;
349314fbfa1STim Northover 
350314fbfa1STim Northover     case AnyCharTy: {
351314fbfa1STim Northover       if (const EnumType *ETy = argTy->getAs<EnumType>()) {
352314fbfa1STim Northover         // If the enum is incomplete we know nothing about the underlying type.
353314fbfa1STim Northover         // Assume that it's 'int'.
354314fbfa1STim Northover         if (!ETy->getDecl()->isComplete())
355314fbfa1STim Northover           return NoMatch;
356314fbfa1STim Northover         argTy = ETy->getDecl()->getIntegerType();
357314fbfa1STim Northover       }
358314fbfa1STim Northover 
359314fbfa1STim Northover       if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
360314fbfa1STim Northover         switch (BT->getKind()) {
361314fbfa1STim Northover           default:
362314fbfa1STim Northover             break;
363314fbfa1STim Northover           case BuiltinType::Char_S:
364314fbfa1STim Northover           case BuiltinType::SChar:
365314fbfa1STim Northover           case BuiltinType::UChar:
366314fbfa1STim Northover           case BuiltinType::Char_U:
3675741d19fSErik Pilkington           case BuiltinType::Bool:
368314fbfa1STim Northover             return Match;
369314fbfa1STim Northover         }
370314fbfa1STim Northover       return NoMatch;
371314fbfa1STim Northover     }
372314fbfa1STim Northover 
373314fbfa1STim Northover     case SpecificTy: {
374314fbfa1STim Northover       if (const EnumType *ETy = argTy->getAs<EnumType>()) {
375314fbfa1STim Northover         // If the enum is incomplete we know nothing about the underlying type.
376314fbfa1STim Northover         // Assume that it's 'int'.
377314fbfa1STim Northover         if (!ETy->getDecl()->isComplete())
378314fbfa1STim Northover           argTy = C.IntTy;
379314fbfa1STim Northover         else
380314fbfa1STim Northover           argTy = ETy->getDecl()->getIntegerType();
381314fbfa1STim Northover       }
382314fbfa1STim Northover       argTy = C.getCanonicalType(argTy).getUnqualifiedType();
383314fbfa1STim Northover 
384314fbfa1STim Northover       if (T == argTy)
385314fbfa1STim Northover         return Match;
386314fbfa1STim Northover       // Check for "compatible types".
387314fbfa1STim Northover       if (const BuiltinType *BT = argTy->getAs<BuiltinType>())
388314fbfa1STim Northover         switch (BT->getKind()) {
389314fbfa1STim Northover           default:
390314fbfa1STim Northover             break;
391314fbfa1STim Northover           case BuiltinType::Char_S:
392314fbfa1STim Northover           case BuiltinType::SChar:
393314fbfa1STim Northover           case BuiltinType::Char_U:
394314fbfa1STim Northover           case BuiltinType::UChar:
3955741d19fSErik Pilkington           case BuiltinType::Bool:
396cc01d642SNathan Huckleberry             if (T == C.UnsignedShortTy || T == C.ShortTy)
397f7766b1eSErik Pilkington               return NoMatchTypeConfusion;
398314fbfa1STim Northover             return T == C.UnsignedCharTy || T == C.SignedCharTy ? Match
399314fbfa1STim Northover                                                                 : NoMatch;
400314fbfa1STim Northover           case BuiltinType::Short:
401314fbfa1STim Northover             return T == C.UnsignedShortTy ? Match : NoMatch;
402314fbfa1STim Northover           case BuiltinType::UShort:
403314fbfa1STim Northover             return T == C.ShortTy ? Match : NoMatch;
404314fbfa1STim Northover           case BuiltinType::Int:
405314fbfa1STim Northover             return T == C.UnsignedIntTy ? Match : NoMatch;
406314fbfa1STim Northover           case BuiltinType::UInt:
407314fbfa1STim Northover             return T == C.IntTy ? Match : NoMatch;
408314fbfa1STim Northover           case BuiltinType::Long:
409314fbfa1STim Northover             return T == C.UnsignedLongTy ? Match : NoMatch;
410314fbfa1STim Northover           case BuiltinType::ULong:
411314fbfa1STim Northover             return T == C.LongTy ? Match : NoMatch;
412314fbfa1STim Northover           case BuiltinType::LongLong:
413314fbfa1STim Northover             return T == C.UnsignedLongLongTy ? Match : NoMatch;
414314fbfa1STim Northover           case BuiltinType::ULongLong:
415314fbfa1STim Northover             return T == C.LongLongTy ? Match : NoMatch;
416314fbfa1STim Northover         }
417314fbfa1STim Northover       return NoMatch;
418314fbfa1STim Northover     }
419314fbfa1STim Northover 
420314fbfa1STim Northover     case CStrTy: {
421314fbfa1STim Northover       const PointerType *PT = argTy->getAs<PointerType>();
422314fbfa1STim Northover       if (!PT)
423314fbfa1STim Northover         return NoMatch;
424314fbfa1STim Northover       QualType pointeeTy = PT->getPointeeType();
425314fbfa1STim Northover       if (const BuiltinType *BT = pointeeTy->getAs<BuiltinType>())
426314fbfa1STim Northover         switch (BT->getKind()) {
427314fbfa1STim Northover           case BuiltinType::Char_U:
428314fbfa1STim Northover           case BuiltinType::UChar:
429314fbfa1STim Northover           case BuiltinType::Char_S:
430314fbfa1STim Northover           case BuiltinType::SChar:
431314fbfa1STim Northover             return Match;
432314fbfa1STim Northover           default:
433314fbfa1STim Northover             break;
434314fbfa1STim Northover         }
435314fbfa1STim Northover 
436314fbfa1STim Northover       return NoMatch;
437314fbfa1STim Northover     }
438314fbfa1STim Northover 
439314fbfa1STim Northover     case WCStrTy: {
440314fbfa1STim Northover       const PointerType *PT = argTy->getAs<PointerType>();
441314fbfa1STim Northover       if (!PT)
442314fbfa1STim Northover         return NoMatch;
443314fbfa1STim Northover       QualType pointeeTy =
444314fbfa1STim Northover         C.getCanonicalType(PT->getPointeeType()).getUnqualifiedType();
445314fbfa1STim Northover       return pointeeTy == C.getWideCharType() ? Match : NoMatch;
446314fbfa1STim Northover     }
447314fbfa1STim Northover 
448314fbfa1STim Northover     case WIntTy: {
449314fbfa1STim Northover       QualType WInt = C.getCanonicalType(C.getWIntType()).getUnqualifiedType();
450314fbfa1STim Northover 
451314fbfa1STim Northover       if (C.getCanonicalType(argTy).getUnqualifiedType() == WInt)
452314fbfa1STim Northover         return Match;
453314fbfa1STim Northover 
454314fbfa1STim Northover       QualType PromoArg = argTy->isPromotableIntegerType()
455314fbfa1STim Northover                               ? C.getPromotedIntegerType(argTy)
456314fbfa1STim Northover                               : argTy;
457314fbfa1STim Northover       PromoArg = C.getCanonicalType(PromoArg).getUnqualifiedType();
458314fbfa1STim Northover 
459314fbfa1STim Northover       // If the promoted argument is the corresponding signed type of the
460314fbfa1STim Northover       // wint_t type, then it should match.
461314fbfa1STim Northover       if (PromoArg->hasSignedIntegerRepresentation() &&
462314fbfa1STim Northover           C.getCorrespondingUnsignedType(PromoArg) == WInt)
463314fbfa1STim Northover         return Match;
464314fbfa1STim Northover 
465314fbfa1STim Northover       return WInt == PromoArg ? Match : NoMatch;
466314fbfa1STim Northover     }
467314fbfa1STim Northover 
468314fbfa1STim Northover     case CPointerTy:
469314fbfa1STim Northover       if (argTy->isVoidPointerType()) {
470314fbfa1STim Northover         return Match;
471314fbfa1STim Northover       } if (argTy->isPointerType() || argTy->isObjCObjectPointerType() ||
472314fbfa1STim Northover             argTy->isBlockPointerType() || argTy->isNullPtrType()) {
473314fbfa1STim Northover         return NoMatchPedantic;
474314fbfa1STim Northover       } else {
475314fbfa1STim Northover         return NoMatch;
476314fbfa1STim Northover       }
477314fbfa1STim Northover 
478314fbfa1STim Northover     case ObjCPointerTy: {
479314fbfa1STim Northover       if (argTy->getAs<ObjCObjectPointerType>() ||
480314fbfa1STim Northover           argTy->getAs<BlockPointerType>())
481314fbfa1STim Northover         return Match;
482314fbfa1STim Northover 
483314fbfa1STim Northover       // Handle implicit toll-free bridging.
484314fbfa1STim Northover       if (const PointerType *PT = argTy->getAs<PointerType>()) {
485314fbfa1STim Northover         // Things such as CFTypeRef are really just opaque pointers
486314fbfa1STim Northover         // to C structs representing CF types that can often be bridged
487314fbfa1STim Northover         // to Objective-C objects.  Since the compiler doesn't know which
488314fbfa1STim Northover         // structs can be toll-free bridged, we just accept them all.
489314fbfa1STim Northover         QualType pointee = PT->getPointeeType();
490314fbfa1STim Northover         if (pointee->getAsStructureType() || pointee->isVoidType())
491314fbfa1STim Northover           return Match;
492314fbfa1STim Northover       }
493314fbfa1STim Northover       return NoMatch;
494314fbfa1STim Northover     }
495314fbfa1STim Northover   }
496314fbfa1STim Northover 
497314fbfa1STim Northover   llvm_unreachable("Invalid ArgType Kind!");
498314fbfa1STim Northover }
499314fbfa1STim Northover 
makeVectorType(ASTContext & C,unsigned NumElts) const5000ff50d49SMatt Arsenault ArgType ArgType::makeVectorType(ASTContext &C, unsigned NumElts) const {
50158fc8082SMatt Arsenault   // Check for valid vector element types.
50258fc8082SMatt Arsenault   if (T.isNull())
5030ff50d49SMatt Arsenault     return ArgType::Invalid();
5040ff50d49SMatt Arsenault 
5050ff50d49SMatt Arsenault   QualType Vec = C.getExtVectorType(T, NumElts);
5060ff50d49SMatt Arsenault   return ArgType(Vec, Name);
5070ff50d49SMatt Arsenault }
5080ff50d49SMatt Arsenault 
getRepresentativeType(ASTContext & C) const509314fbfa1STim Northover QualType ArgType::getRepresentativeType(ASTContext &C) const {
510314fbfa1STim Northover   QualType Res;
511314fbfa1STim Northover   switch (K) {
512314fbfa1STim Northover     case InvalidTy:
513314fbfa1STim Northover       llvm_unreachable("No representative type for Invalid ArgType");
514314fbfa1STim Northover     case UnknownTy:
515314fbfa1STim Northover       llvm_unreachable("No representative type for Unknown ArgType");
516314fbfa1STim Northover     case AnyCharTy:
517314fbfa1STim Northover       Res = C.CharTy;
518314fbfa1STim Northover       break;
519314fbfa1STim Northover     case SpecificTy:
520314fbfa1STim Northover       Res = T;
521314fbfa1STim Northover       break;
522314fbfa1STim Northover     case CStrTy:
523314fbfa1STim Northover       Res = C.getPointerType(C.CharTy);
524314fbfa1STim Northover       break;
525314fbfa1STim Northover     case WCStrTy:
526314fbfa1STim Northover       Res = C.getPointerType(C.getWideCharType());
527314fbfa1STim Northover       break;
528314fbfa1STim Northover     case ObjCPointerTy:
529314fbfa1STim Northover       Res = C.ObjCBuiltinIdTy;
530314fbfa1STim Northover       break;
531314fbfa1STim Northover     case CPointerTy:
532314fbfa1STim Northover       Res = C.VoidPtrTy;
533314fbfa1STim Northover       break;
534314fbfa1STim Northover     case WIntTy: {
535314fbfa1STim Northover       Res = C.getWIntType();
536314fbfa1STim Northover       break;
537314fbfa1STim Northover     }
538314fbfa1STim Northover   }
539314fbfa1STim Northover 
540314fbfa1STim Northover   if (Ptr)
541314fbfa1STim Northover     Res = C.getPointerType(Res);
542314fbfa1STim Northover   return Res;
543314fbfa1STim Northover }
544314fbfa1STim Northover 
getRepresentativeTypeName(ASTContext & C) const545314fbfa1STim Northover std::string ArgType::getRepresentativeTypeName(ASTContext &C) const {
5465fee6936SJessica Clarke   std::string S = getRepresentativeType(C).getAsString(C.getPrintingPolicy());
547314fbfa1STim Northover 
548314fbfa1STim Northover   std::string Alias;
549314fbfa1STim Northover   if (Name) {
550314fbfa1STim Northover     // Use a specific name for this type, e.g. "size_t".
551314fbfa1STim Northover     Alias = Name;
552314fbfa1STim Northover     if (Ptr) {
553314fbfa1STim Northover       // If ArgType is actually a pointer to T, append an asterisk.
554314fbfa1STim Northover       Alias += (Alias[Alias.size()-1] == '*') ? "*" : " *";
555314fbfa1STim Northover     }
556314fbfa1STim Northover     // If Alias is the same as the underlying type, e.g. wchar_t, then drop it.
557314fbfa1STim Northover     if (S == Alias)
558314fbfa1STim Northover       Alias.clear();
559314fbfa1STim Northover   }
560314fbfa1STim Northover 
561314fbfa1STim Northover   if (!Alias.empty())
562314fbfa1STim Northover     return std::string("'") + Alias + "' (aka '" + S + "')";
563314fbfa1STim Northover   return std::string("'") + S + "'";
564314fbfa1STim Northover }
565314fbfa1STim Northover 
566314fbfa1STim Northover 
567314fbfa1STim Northover //===----------------------------------------------------------------------===//
568314fbfa1STim Northover // Methods on OptionalAmount.
569314fbfa1STim Northover //===----------------------------------------------------------------------===//
570314fbfa1STim Northover 
571314fbfa1STim Northover ArgType
getArgType(ASTContext & Ctx) const572314fbfa1STim Northover analyze_format_string::OptionalAmount::getArgType(ASTContext &Ctx) const {
573314fbfa1STim Northover   return Ctx.IntTy;
574314fbfa1STim Northover }
575314fbfa1STim Northover 
576314fbfa1STim Northover //===----------------------------------------------------------------------===//
577314fbfa1STim Northover // Methods on LengthModifier.
578314fbfa1STim Northover //===----------------------------------------------------------------------===//
579314fbfa1STim Northover 
580314fbfa1STim Northover const char *
toString() const581314fbfa1STim Northover analyze_format_string::LengthModifier::toString() const {
582314fbfa1STim Northover   switch (kind) {
583314fbfa1STim Northover   case AsChar:
584314fbfa1STim Northover     return "hh";
585314fbfa1STim Northover   case AsShort:
586314fbfa1STim Northover     return "h";
58758fc8082SMatt Arsenault   case AsShortLong:
58858fc8082SMatt Arsenault     return "hl";
589314fbfa1STim Northover   case AsLong: // or AsWideChar
590314fbfa1STim Northover     return "l";
591314fbfa1STim Northover   case AsLongLong:
592314fbfa1STim Northover     return "ll";
593314fbfa1STim Northover   case AsQuad:
594314fbfa1STim Northover     return "q";
595314fbfa1STim Northover   case AsIntMax:
596314fbfa1STim Northover     return "j";
597314fbfa1STim Northover   case AsSizeT:
598314fbfa1STim Northover     return "z";
599314fbfa1STim Northover   case AsPtrDiff:
600314fbfa1STim Northover     return "t";
601314fbfa1STim Northover   case AsInt32:
602314fbfa1STim Northover     return "I32";
603314fbfa1STim Northover   case AsInt3264:
604314fbfa1STim Northover     return "I";
605314fbfa1STim Northover   case AsInt64:
606314fbfa1STim Northover     return "I64";
607314fbfa1STim Northover   case AsLongDouble:
608314fbfa1STim Northover     return "L";
609314fbfa1STim Northover   case AsAllocate:
610314fbfa1STim Northover     return "a";
611314fbfa1STim Northover   case AsMAllocate:
612314fbfa1STim Northover     return "m";
613314fbfa1STim Northover   case AsWide:
614314fbfa1STim Northover     return "w";
615314fbfa1STim Northover   case None:
616314fbfa1STim Northover     return "";
617314fbfa1STim Northover   }
618314fbfa1STim Northover   return nullptr;
619314fbfa1STim Northover }
620314fbfa1STim Northover 
621314fbfa1STim Northover //===----------------------------------------------------------------------===//
622314fbfa1STim Northover // Methods on ConversionSpecifier.
623314fbfa1STim Northover //===----------------------------------------------------------------------===//
624314fbfa1STim Northover 
toString() const625314fbfa1STim Northover const char *ConversionSpecifier::toString() const {
626314fbfa1STim Northover   switch (kind) {
627314fbfa1STim Northover   case dArg: return "d";
628314fbfa1STim Northover   case DArg: return "D";
629314fbfa1STim Northover   case iArg: return "i";
630314fbfa1STim Northover   case oArg: return "o";
631314fbfa1STim Northover   case OArg: return "O";
632314fbfa1STim Northover   case uArg: return "u";
633314fbfa1STim Northover   case UArg: return "U";
634314fbfa1STim Northover   case xArg: return "x";
635314fbfa1STim Northover   case XArg: return "X";
636314fbfa1STim Northover   case fArg: return "f";
637314fbfa1STim Northover   case FArg: return "F";
638314fbfa1STim Northover   case eArg: return "e";
639314fbfa1STim Northover   case EArg: return "E";
640314fbfa1STim Northover   case gArg: return "g";
641314fbfa1STim Northover   case GArg: return "G";
642314fbfa1STim Northover   case aArg: return "a";
643314fbfa1STim Northover   case AArg: return "A";
644314fbfa1STim Northover   case cArg: return "c";
645314fbfa1STim Northover   case sArg: return "s";
646314fbfa1STim Northover   case pArg: return "p";
647314fbfa1STim Northover   case PArg:
648314fbfa1STim Northover     return "P";
649314fbfa1STim Northover   case nArg: return "n";
650314fbfa1STim Northover   case PercentArg:  return "%";
651314fbfa1STim Northover   case ScanListArg: return "[";
652314fbfa1STim Northover   case InvalidSpecifier: return nullptr;
653314fbfa1STim Northover 
654314fbfa1STim Northover   // POSIX unicode extensions.
655314fbfa1STim Northover   case CArg: return "C";
656314fbfa1STim Northover   case SArg: return "S";
657314fbfa1STim Northover 
658314fbfa1STim Northover   // Objective-C specific specifiers.
659314fbfa1STim Northover   case ObjCObjArg: return "@";
660314fbfa1STim Northover 
661314fbfa1STim Northover   // FreeBSD kernel specific specifiers.
662314fbfa1STim Northover   case FreeBSDbArg: return "b";
663314fbfa1STim Northover   case FreeBSDDArg: return "D";
664314fbfa1STim Northover   case FreeBSDrArg: return "r";
665314fbfa1STim Northover   case FreeBSDyArg: return "y";
666314fbfa1STim Northover 
667314fbfa1STim Northover   // GlibC specific specifiers.
668314fbfa1STim Northover   case PrintErrno: return "m";
669314fbfa1STim Northover 
670314fbfa1STim Northover   // MS specific specifiers.
671314fbfa1STim Northover   case ZArg: return "Z";
672314fbfa1STim Northover   }
673314fbfa1STim Northover   return nullptr;
674314fbfa1STim Northover }
675314fbfa1STim Northover 
676314fbfa1STim Northover Optional<ConversionSpecifier>
getStandardSpecifier() const677314fbfa1STim Northover ConversionSpecifier::getStandardSpecifier() const {
678314fbfa1STim Northover   ConversionSpecifier::Kind NewKind;
679314fbfa1STim Northover 
680314fbfa1STim Northover   switch (getKind()) {
681314fbfa1STim Northover   default:
682314fbfa1STim Northover     return None;
683314fbfa1STim Northover   case DArg:
684314fbfa1STim Northover     NewKind = dArg;
685314fbfa1STim Northover     break;
686314fbfa1STim Northover   case UArg:
687314fbfa1STim Northover     NewKind = uArg;
688314fbfa1STim Northover     break;
689314fbfa1STim Northover   case OArg:
690314fbfa1STim Northover     NewKind = oArg;
691314fbfa1STim Northover     break;
692314fbfa1STim Northover   }
693314fbfa1STim Northover 
694314fbfa1STim Northover   ConversionSpecifier FixedCS(*this);
695314fbfa1STim Northover   FixedCS.setKind(NewKind);
696314fbfa1STim Northover   return FixedCS;
697314fbfa1STim Northover }
698314fbfa1STim Northover 
699314fbfa1STim Northover //===----------------------------------------------------------------------===//
700314fbfa1STim Northover // Methods on OptionalAmount.
701314fbfa1STim Northover //===----------------------------------------------------------------------===//
702314fbfa1STim Northover 
toString(raw_ostream & os) const703314fbfa1STim Northover void OptionalAmount::toString(raw_ostream &os) const {
704314fbfa1STim Northover   switch (hs) {
705314fbfa1STim Northover   case Invalid:
706314fbfa1STim Northover   case NotSpecified:
707314fbfa1STim Northover     return;
708314fbfa1STim Northover   case Arg:
709314fbfa1STim Northover     if (UsesDotPrefix)
710314fbfa1STim Northover         os << ".";
711314fbfa1STim Northover     if (usesPositionalArg())
712314fbfa1STim Northover       os << "*" << getPositionalArgIndex() << "$";
713314fbfa1STim Northover     else
714314fbfa1STim Northover       os << "*";
715314fbfa1STim Northover     break;
716314fbfa1STim Northover   case Constant:
717314fbfa1STim Northover     if (UsesDotPrefix)
718314fbfa1STim Northover         os << ".";
719314fbfa1STim Northover     os << amt;
720314fbfa1STim Northover     break;
721314fbfa1STim Northover   }
722314fbfa1STim Northover }
723314fbfa1STim Northover 
hasValidLengthModifier(const TargetInfo & Target,const LangOptions & LO) const72458fc8082SMatt Arsenault bool FormatSpecifier::hasValidLengthModifier(const TargetInfo &Target,
72558fc8082SMatt Arsenault                                              const LangOptions &LO) const {
726314fbfa1STim Northover   switch (LM.getKind()) {
727314fbfa1STim Northover     case LengthModifier::None:
728314fbfa1STim Northover       return true;
729314fbfa1STim Northover 
730314fbfa1STim Northover     // Handle most integer flags
731314fbfa1STim Northover     case LengthModifier::AsShort:
73258fc8082SMatt Arsenault       // Length modifier only applies to FP vectors.
73358fc8082SMatt Arsenault       if (LO.OpenCL && CS.isDoubleArg())
73458fc8082SMatt Arsenault         return !VectorNumElts.isInvalid();
73558fc8082SMatt Arsenault 
736314fbfa1STim Northover       if (Target.getTriple().isOSMSVCRT()) {
737314fbfa1STim Northover         switch (CS.getKind()) {
738314fbfa1STim Northover           case ConversionSpecifier::cArg:
739314fbfa1STim Northover           case ConversionSpecifier::CArg:
740314fbfa1STim Northover           case ConversionSpecifier::sArg:
741314fbfa1STim Northover           case ConversionSpecifier::SArg:
742314fbfa1STim Northover           case ConversionSpecifier::ZArg:
743314fbfa1STim Northover             return true;
744314fbfa1STim Northover           default:
745314fbfa1STim Northover             break;
746314fbfa1STim Northover         }
747314fbfa1STim Northover       }
748314fbfa1STim Northover       LLVM_FALLTHROUGH;
749314fbfa1STim Northover     case LengthModifier::AsChar:
750314fbfa1STim Northover     case LengthModifier::AsLongLong:
751314fbfa1STim Northover     case LengthModifier::AsQuad:
752314fbfa1STim Northover     case LengthModifier::AsIntMax:
753314fbfa1STim Northover     case LengthModifier::AsSizeT:
754314fbfa1STim Northover     case LengthModifier::AsPtrDiff:
755314fbfa1STim Northover       switch (CS.getKind()) {
756314fbfa1STim Northover         case ConversionSpecifier::dArg:
757314fbfa1STim Northover         case ConversionSpecifier::DArg:
758314fbfa1STim Northover         case ConversionSpecifier::iArg:
759314fbfa1STim Northover         case ConversionSpecifier::oArg:
760314fbfa1STim Northover         case ConversionSpecifier::OArg:
761314fbfa1STim Northover         case ConversionSpecifier::uArg:
762314fbfa1STim Northover         case ConversionSpecifier::UArg:
763314fbfa1STim Northover         case ConversionSpecifier::xArg:
764314fbfa1STim Northover         case ConversionSpecifier::XArg:
765314fbfa1STim Northover         case ConversionSpecifier::nArg:
766314fbfa1STim Northover           return true;
767314fbfa1STim Northover         case ConversionSpecifier::FreeBSDrArg:
768314fbfa1STim Northover         case ConversionSpecifier::FreeBSDyArg:
769b2c6251cSPaul Robinson           return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
770314fbfa1STim Northover         default:
771314fbfa1STim Northover           return false;
772314fbfa1STim Northover       }
773314fbfa1STim Northover 
77458fc8082SMatt Arsenault     case LengthModifier::AsShortLong:
77558fc8082SMatt Arsenault       return LO.OpenCL && !VectorNumElts.isInvalid();
77658fc8082SMatt Arsenault 
777314fbfa1STim Northover     // Handle 'l' flag
778314fbfa1STim Northover     case LengthModifier::AsLong: // or AsWideChar
77958fc8082SMatt Arsenault       if (CS.isDoubleArg()) {
78058fc8082SMatt Arsenault         // Invalid for OpenCL FP scalars.
78158fc8082SMatt Arsenault         if (LO.OpenCL && VectorNumElts.isInvalid())
78258fc8082SMatt Arsenault           return false;
78358fc8082SMatt Arsenault         return true;
78458fc8082SMatt Arsenault       }
78558fc8082SMatt Arsenault 
786314fbfa1STim Northover       switch (CS.getKind()) {
787314fbfa1STim Northover         case ConversionSpecifier::dArg:
788314fbfa1STim Northover         case ConversionSpecifier::DArg:
789314fbfa1STim Northover         case ConversionSpecifier::iArg:
790314fbfa1STim Northover         case ConversionSpecifier::oArg:
791314fbfa1STim Northover         case ConversionSpecifier::OArg:
792314fbfa1STim Northover         case ConversionSpecifier::uArg:
793314fbfa1STim Northover         case ConversionSpecifier::UArg:
794314fbfa1STim Northover         case ConversionSpecifier::xArg:
795314fbfa1STim Northover         case ConversionSpecifier::XArg:
796314fbfa1STim Northover         case ConversionSpecifier::nArg:
797314fbfa1STim Northover         case ConversionSpecifier::cArg:
798314fbfa1STim Northover         case ConversionSpecifier::sArg:
799314fbfa1STim Northover         case ConversionSpecifier::ScanListArg:
800314fbfa1STim Northover         case ConversionSpecifier::ZArg:
801314fbfa1STim Northover           return true;
802314fbfa1STim Northover         case ConversionSpecifier::FreeBSDrArg:
803314fbfa1STim Northover         case ConversionSpecifier::FreeBSDyArg:
804b2c6251cSPaul Robinson           return Target.getTriple().isOSFreeBSD() || Target.getTriple().isPS();
805314fbfa1STim Northover         default:
806314fbfa1STim Northover           return false;
807314fbfa1STim Northover       }
808314fbfa1STim Northover 
809314fbfa1STim Northover     case LengthModifier::AsLongDouble:
810314fbfa1STim Northover       switch (CS.getKind()) {
811314fbfa1STim Northover         case ConversionSpecifier::aArg:
812314fbfa1STim Northover         case ConversionSpecifier::AArg:
813314fbfa1STim Northover         case ConversionSpecifier::fArg:
814314fbfa1STim Northover         case ConversionSpecifier::FArg:
815314fbfa1STim Northover         case ConversionSpecifier::eArg:
816314fbfa1STim Northover         case ConversionSpecifier::EArg:
817314fbfa1STim Northover         case ConversionSpecifier::gArg:
818314fbfa1STim Northover         case ConversionSpecifier::GArg:
819314fbfa1STim Northover           return true;
820314fbfa1STim Northover         // GNU libc extension.
821314fbfa1STim Northover         case ConversionSpecifier::dArg:
822314fbfa1STim Northover         case ConversionSpecifier::iArg:
823314fbfa1STim Northover         case ConversionSpecifier::oArg:
824314fbfa1STim Northover         case ConversionSpecifier::uArg:
825314fbfa1STim Northover         case ConversionSpecifier::xArg:
826314fbfa1STim Northover         case ConversionSpecifier::XArg:
827314fbfa1STim Northover           return !Target.getTriple().isOSDarwin() &&
828314fbfa1STim Northover                  !Target.getTriple().isOSWindows();
829314fbfa1STim Northover         default:
830314fbfa1STim Northover           return false;
831314fbfa1STim Northover       }
832314fbfa1STim Northover 
833314fbfa1STim Northover     case LengthModifier::AsAllocate:
834314fbfa1STim Northover       switch (CS.getKind()) {
835314fbfa1STim Northover         case ConversionSpecifier::sArg:
836314fbfa1STim Northover         case ConversionSpecifier::SArg:
837314fbfa1STim Northover         case ConversionSpecifier::ScanListArg:
838314fbfa1STim Northover           return true;
839314fbfa1STim Northover         default:
840314fbfa1STim Northover           return false;
841314fbfa1STim Northover       }
842314fbfa1STim Northover 
843314fbfa1STim Northover     case LengthModifier::AsMAllocate:
844314fbfa1STim Northover       switch (CS.getKind()) {
845314fbfa1STim Northover         case ConversionSpecifier::cArg:
846314fbfa1STim Northover         case ConversionSpecifier::CArg:
847314fbfa1STim Northover         case ConversionSpecifier::sArg:
848314fbfa1STim Northover         case ConversionSpecifier::SArg:
849314fbfa1STim Northover         case ConversionSpecifier::ScanListArg:
850314fbfa1STim Northover           return true;
851314fbfa1STim Northover         default:
852314fbfa1STim Northover           return false;
853314fbfa1STim Northover       }
854314fbfa1STim Northover     case LengthModifier::AsInt32:
855314fbfa1STim Northover     case LengthModifier::AsInt3264:
856314fbfa1STim Northover     case LengthModifier::AsInt64:
857314fbfa1STim Northover       switch (CS.getKind()) {
858314fbfa1STim Northover         case ConversionSpecifier::dArg:
859314fbfa1STim Northover         case ConversionSpecifier::iArg:
860314fbfa1STim Northover         case ConversionSpecifier::oArg:
861314fbfa1STim Northover         case ConversionSpecifier::uArg:
862314fbfa1STim Northover         case ConversionSpecifier::xArg:
863314fbfa1STim Northover         case ConversionSpecifier::XArg:
864314fbfa1STim Northover           return Target.getTriple().isOSMSVCRT();
865314fbfa1STim Northover         default:
866314fbfa1STim Northover           return false;
867314fbfa1STim Northover       }
868314fbfa1STim Northover     case LengthModifier::AsWide:
869314fbfa1STim Northover       switch (CS.getKind()) {
870314fbfa1STim Northover         case ConversionSpecifier::cArg:
871314fbfa1STim Northover         case ConversionSpecifier::CArg:
872314fbfa1STim Northover         case ConversionSpecifier::sArg:
873314fbfa1STim Northover         case ConversionSpecifier::SArg:
874314fbfa1STim Northover         case ConversionSpecifier::ZArg:
875314fbfa1STim Northover           return Target.getTriple().isOSMSVCRT();
876314fbfa1STim Northover         default:
877314fbfa1STim Northover           return false;
878314fbfa1STim Northover       }
879314fbfa1STim Northover   }
880314fbfa1STim Northover   llvm_unreachable("Invalid LengthModifier Kind!");
881314fbfa1STim Northover }
882314fbfa1STim Northover 
hasStandardLengthModifier() const883314fbfa1STim Northover bool FormatSpecifier::hasStandardLengthModifier() const {
884314fbfa1STim Northover   switch (LM.getKind()) {
885314fbfa1STim Northover     case LengthModifier::None:
886314fbfa1STim Northover     case LengthModifier::AsChar:
887314fbfa1STim Northover     case LengthModifier::AsShort:
888314fbfa1STim Northover     case LengthModifier::AsLong:
889314fbfa1STim Northover     case LengthModifier::AsLongLong:
890314fbfa1STim Northover     case LengthModifier::AsIntMax:
891314fbfa1STim Northover     case LengthModifier::AsSizeT:
892314fbfa1STim Northover     case LengthModifier::AsPtrDiff:
893314fbfa1STim Northover     case LengthModifier::AsLongDouble:
894314fbfa1STim Northover       return true;
895314fbfa1STim Northover     case LengthModifier::AsAllocate:
896314fbfa1STim Northover     case LengthModifier::AsMAllocate:
897314fbfa1STim Northover     case LengthModifier::AsQuad:
898314fbfa1STim Northover     case LengthModifier::AsInt32:
899314fbfa1STim Northover     case LengthModifier::AsInt3264:
900314fbfa1STim Northover     case LengthModifier::AsInt64:
901314fbfa1STim Northover     case LengthModifier::AsWide:
90258fc8082SMatt Arsenault     case LengthModifier::AsShortLong: // ???
903314fbfa1STim Northover       return false;
904314fbfa1STim Northover   }
905314fbfa1STim Northover   llvm_unreachable("Invalid LengthModifier Kind!");
906314fbfa1STim Northover }
907314fbfa1STim Northover 
hasStandardConversionSpecifier(const LangOptions & LangOpt) const908314fbfa1STim Northover bool FormatSpecifier::hasStandardConversionSpecifier(
909314fbfa1STim Northover     const LangOptions &LangOpt) const {
910314fbfa1STim Northover   switch (CS.getKind()) {
911314fbfa1STim Northover     case ConversionSpecifier::cArg:
912314fbfa1STim Northover     case ConversionSpecifier::dArg:
913314fbfa1STim Northover     case ConversionSpecifier::iArg:
914314fbfa1STim Northover     case ConversionSpecifier::oArg:
915314fbfa1STim Northover     case ConversionSpecifier::uArg:
916314fbfa1STim Northover     case ConversionSpecifier::xArg:
917314fbfa1STim Northover     case ConversionSpecifier::XArg:
918314fbfa1STim Northover     case ConversionSpecifier::fArg:
919314fbfa1STim Northover     case ConversionSpecifier::FArg:
920314fbfa1STim Northover     case ConversionSpecifier::eArg:
921314fbfa1STim Northover     case ConversionSpecifier::EArg:
922314fbfa1STim Northover     case ConversionSpecifier::gArg:
923314fbfa1STim Northover     case ConversionSpecifier::GArg:
924314fbfa1STim Northover     case ConversionSpecifier::aArg:
925314fbfa1STim Northover     case ConversionSpecifier::AArg:
926314fbfa1STim Northover     case ConversionSpecifier::sArg:
927314fbfa1STim Northover     case ConversionSpecifier::pArg:
928314fbfa1STim Northover     case ConversionSpecifier::nArg:
929314fbfa1STim Northover     case ConversionSpecifier::ObjCObjArg:
930314fbfa1STim Northover     case ConversionSpecifier::ScanListArg:
931314fbfa1STim Northover     case ConversionSpecifier::PercentArg:
932314fbfa1STim Northover     case ConversionSpecifier::PArg:
933314fbfa1STim Northover       return true;
934314fbfa1STim Northover     case ConversionSpecifier::CArg:
935314fbfa1STim Northover     case ConversionSpecifier::SArg:
936314fbfa1STim Northover       return LangOpt.ObjC;
937314fbfa1STim Northover     case ConversionSpecifier::InvalidSpecifier:
938314fbfa1STim Northover     case ConversionSpecifier::FreeBSDbArg:
939314fbfa1STim Northover     case ConversionSpecifier::FreeBSDDArg:
940314fbfa1STim Northover     case ConversionSpecifier::FreeBSDrArg:
941314fbfa1STim Northover     case ConversionSpecifier::FreeBSDyArg:
942314fbfa1STim Northover     case ConversionSpecifier::PrintErrno:
943314fbfa1STim Northover     case ConversionSpecifier::DArg:
944314fbfa1STim Northover     case ConversionSpecifier::OArg:
945314fbfa1STim Northover     case ConversionSpecifier::UArg:
946314fbfa1STim Northover     case ConversionSpecifier::ZArg:
947314fbfa1STim Northover       return false;
948314fbfa1STim Northover   }
949314fbfa1STim Northover   llvm_unreachable("Invalid ConversionSpecifier Kind!");
950314fbfa1STim Northover }
951314fbfa1STim Northover 
hasStandardLengthConversionCombination() const952314fbfa1STim Northover bool FormatSpecifier::hasStandardLengthConversionCombination() const {
953314fbfa1STim Northover   if (LM.getKind() == LengthModifier::AsLongDouble) {
954314fbfa1STim Northover     switch(CS.getKind()) {
955314fbfa1STim Northover         case ConversionSpecifier::dArg:
956314fbfa1STim Northover         case ConversionSpecifier::iArg:
957314fbfa1STim Northover         case ConversionSpecifier::oArg:
958314fbfa1STim Northover         case ConversionSpecifier::uArg:
959314fbfa1STim Northover         case ConversionSpecifier::xArg:
960314fbfa1STim Northover         case ConversionSpecifier::XArg:
961314fbfa1STim Northover           return false;
962314fbfa1STim Northover         default:
963314fbfa1STim Northover           return true;
964314fbfa1STim Northover     }
965314fbfa1STim Northover   }
966314fbfa1STim Northover   return true;
967314fbfa1STim Northover }
968314fbfa1STim Northover 
getCorrectedLengthModifier() const969314fbfa1STim Northover Optional<LengthModifier> FormatSpecifier::getCorrectedLengthModifier() const {
970314fbfa1STim Northover   if (CS.isAnyIntArg() || CS.getKind() == ConversionSpecifier::nArg) {
971314fbfa1STim Northover     if (LM.getKind() == LengthModifier::AsLongDouble ||
972314fbfa1STim Northover         LM.getKind() == LengthModifier::AsQuad) {
973314fbfa1STim Northover       LengthModifier FixedLM(LM);
974314fbfa1STim Northover       FixedLM.setKind(LengthModifier::AsLongLong);
975314fbfa1STim Northover       return FixedLM;
976314fbfa1STim Northover     }
977314fbfa1STim Northover   }
978314fbfa1STim Northover 
979314fbfa1STim Northover   return None;
980314fbfa1STim Northover }
981314fbfa1STim Northover 
namedTypeToLengthModifier(QualType QT,LengthModifier & LM)982314fbfa1STim Northover bool FormatSpecifier::namedTypeToLengthModifier(QualType QT,
983314fbfa1STim Northover                                                 LengthModifier &LM) {
984*888673b6SJonas Devlieghere   assert(isa<TypedefType>(QT) && "Expected a TypedefType");
985*888673b6SJonas Devlieghere   const TypedefNameDecl *Typedef = cast<TypedefType>(QT)->getDecl();
986*888673b6SJonas Devlieghere 
987*888673b6SJonas Devlieghere   for (;;) {
988314fbfa1STim Northover     const IdentifierInfo *Identifier = Typedef->getIdentifier();
989314fbfa1STim Northover     if (Identifier->getName() == "size_t") {
990314fbfa1STim Northover       LM.setKind(LengthModifier::AsSizeT);
991314fbfa1STim Northover       return true;
992314fbfa1STim Northover     } else if (Identifier->getName() == "ssize_t") {
993314fbfa1STim Northover       // Not C99, but common in Unix.
994314fbfa1STim Northover       LM.setKind(LengthModifier::AsSizeT);
995314fbfa1STim Northover       return true;
996314fbfa1STim Northover     } else if (Identifier->getName() == "intmax_t") {
997314fbfa1STim Northover       LM.setKind(LengthModifier::AsIntMax);
998314fbfa1STim Northover       return true;
999314fbfa1STim Northover     } else if (Identifier->getName() == "uintmax_t") {
1000314fbfa1STim Northover       LM.setKind(LengthModifier::AsIntMax);
1001314fbfa1STim Northover       return true;
1002314fbfa1STim Northover     } else if (Identifier->getName() == "ptrdiff_t") {
1003314fbfa1STim Northover       LM.setKind(LengthModifier::AsPtrDiff);
1004314fbfa1STim Northover       return true;
1005314fbfa1STim Northover     }
1006*888673b6SJonas Devlieghere 
1007*888673b6SJonas Devlieghere     QualType T = Typedef->getUnderlyingType();
1008*888673b6SJonas Devlieghere     if (!isa<TypedefType>(T))
1009*888673b6SJonas Devlieghere       break;
1010*888673b6SJonas Devlieghere 
1011*888673b6SJonas Devlieghere     Typedef = cast<TypedefType>(T)->getDecl();
1012314fbfa1STim Northover   }
1013314fbfa1STim Northover   return false;
1014314fbfa1STim Northover }
1015