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