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