1 //== PrintfFormatString.cpp - Analysis of printf format strings --*- C++ -*-==//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Handling of format string in printf and friends.  The structure of format
11 // strings for fprintf() are described in C99 7.19.6.1.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "clang/Analysis/Analyses/FormatString.h"
16 #include "FormatStringParsing.h"
17 #include "clang/Basic/TargetInfo.h"
18 
19 using clang::analyze_format_string::ArgType;
20 using clang::analyze_format_string::FormatStringHandler;
21 using clang::analyze_format_string::LengthModifier;
22 using clang::analyze_format_string::OptionalAmount;
23 using clang::analyze_format_string::ConversionSpecifier;
24 using clang::analyze_printf::PrintfSpecifier;
25 
26 using namespace clang;
27 
28 typedef clang::analyze_format_string::SpecifierResult<PrintfSpecifier>
29         PrintfSpecifierResult;
30 
31 //===----------------------------------------------------------------------===//
32 // Methods for parsing format strings.
33 //===----------------------------------------------------------------------===//
34 
35 using analyze_format_string::ParseNonPositionAmount;
36 
ParsePrecision(FormatStringHandler & H,PrintfSpecifier & FS,const char * Start,const char * & Beg,const char * E,unsigned * argIndex)37 static bool ParsePrecision(FormatStringHandler &H, PrintfSpecifier &FS,
38                            const char *Start, const char *&Beg, const char *E,
39                            unsigned *argIndex) {
40   if (argIndex) {
41     FS.setPrecision(ParseNonPositionAmount(Beg, E, *argIndex));
42   } else {
43     const OptionalAmount Amt = ParsePositionAmount(H, Start, Beg, E,
44                                            analyze_format_string::PrecisionPos);
45     if (Amt.isInvalid())
46       return true;
47     FS.setPrecision(Amt);
48   }
49   return false;
50 }
51 
ParsePrintfSpecifier(FormatStringHandler & H,const char * & Beg,const char * E,unsigned & argIndex,const LangOptions & LO,const TargetInfo & Target,bool Warn)52 static PrintfSpecifierResult ParsePrintfSpecifier(FormatStringHandler &H,
53                                                   const char *&Beg,
54                                                   const char *E,
55                                                   unsigned &argIndex,
56                                                   const LangOptions &LO,
57                                                   const TargetInfo &Target,
58                                                   bool Warn) {
59 
60   using namespace clang::analyze_format_string;
61   using namespace clang::analyze_printf;
62 
63   const char *I = Beg;
64   const char *Start = nullptr;
65   UpdateOnReturn <const char*> UpdateBeg(Beg, I);
66 
67   // Look for a '%' character that indicates the start of a format specifier.
68   for ( ; I != E ; ++I) {
69     char c = *I;
70     if (c == '\0') {
71       // Detect spurious null characters, which are likely errors.
72       H.HandleNullChar(I);
73       return true;
74     }
75     if (c == '%') {
76       Start = I++;  // Record the start of the format specifier.
77       break;
78     }
79   }
80 
81   // No format specifier found?
82   if (!Start)
83     return false;
84 
85   if (I == E) {
86     // No more characters left?
87     if (Warn)
88       H.HandleIncompleteSpecifier(Start, E - Start);
89     return true;
90   }
91 
92   PrintfSpecifier FS;
93   if (ParseArgPosition(H, FS, Start, I, E))
94     return true;
95 
96   if (I == E) {
97     // No more characters left?
98     if (Warn)
99       H.HandleIncompleteSpecifier(Start, E - Start);
100     return true;
101   }
102 
103   // Look for flags (if any).
104   bool hasMore = true;
105   for ( ; I != E; ++I) {
106     switch (*I) {
107       default: hasMore = false; break;
108       case '\'':
109         // FIXME: POSIX specific.  Always accept?
110         FS.setHasThousandsGrouping(I);
111         break;
112       case '-': FS.setIsLeftJustified(I); break;
113       case '+': FS.setHasPlusPrefix(I); break;
114       case ' ': FS.setHasSpacePrefix(I); break;
115       case '#': FS.setHasAlternativeForm(I); break;
116       case '0': FS.setHasLeadingZeros(I); break;
117     }
118     if (!hasMore)
119       break;
120   }
121 
122   if (I == E) {
123     // No more characters left?
124     if (Warn)
125       H.HandleIncompleteSpecifier(Start, E - Start);
126     return true;
127   }
128 
129   // Look for the field width (if any).
130   if (ParseFieldWidth(H, FS, Start, I, E,
131                       FS.usesPositionalArg() ? nullptr : &argIndex))
132     return true;
133 
134   if (I == E) {
135     // No more characters left?
136     if (Warn)
137       H.HandleIncompleteSpecifier(Start, E - Start);
138     return true;
139   }
140 
141   // Look for the precision (if any).
142   if (*I == '.') {
143     ++I;
144     if (I == E) {
145       if (Warn)
146         H.HandleIncompleteSpecifier(Start, E - Start);
147       return true;
148     }
149 
150     if (ParsePrecision(H, FS, Start, I, E,
151                        FS.usesPositionalArg() ? nullptr : &argIndex))
152       return true;
153 
154     if (I == E) {
155       // No more characters left?
156       if (Warn)
157         H.HandleIncompleteSpecifier(Start, E - Start);
158       return true;
159     }
160   }
161 
162   // Look for the length modifier.
163   if (ParseLengthModifier(FS, I, E, LO) && I == E) {
164     // No more characters left?
165     if (Warn)
166       H.HandleIncompleteSpecifier(Start, E - Start);
167     return true;
168   }
169 
170   if (*I == '\0') {
171     // Detect spurious null characters, which are likely errors.
172     H.HandleNullChar(I);
173     return true;
174   }
175 
176   // Finally, look for the conversion specifier.
177   const char *conversionPosition = I++;
178   ConversionSpecifier::Kind k = ConversionSpecifier::InvalidSpecifier;
179   switch (*conversionPosition) {
180     default:
181       break;
182     // C99: 7.19.6.1 (section 8).
183     case '%': k = ConversionSpecifier::PercentArg;   break;
184     case 'A': k = ConversionSpecifier::AArg; break;
185     case 'E': k = ConversionSpecifier::EArg; break;
186     case 'F': k = ConversionSpecifier::FArg; break;
187     case 'G': k = ConversionSpecifier::GArg; break;
188     case 'X': k = ConversionSpecifier::XArg; break;
189     case 'a': k = ConversionSpecifier::aArg; break;
190     case 'c': k = ConversionSpecifier::cArg; break;
191     case 'd': k = ConversionSpecifier::dArg; break;
192     case 'e': k = ConversionSpecifier::eArg; break;
193     case 'f': k = ConversionSpecifier::fArg; break;
194     case 'g': k = ConversionSpecifier::gArg; break;
195     case 'i': k = ConversionSpecifier::iArg; break;
196     case 'n': k = ConversionSpecifier::nArg; break;
197     case 'o': k = ConversionSpecifier::oArg; break;
198     case 'p': k = ConversionSpecifier::pArg; break;
199     case 's': k = ConversionSpecifier::sArg; break;
200     case 'u': k = ConversionSpecifier::uArg; break;
201     case 'x': k = ConversionSpecifier::xArg; break;
202     // POSIX specific.
203     case 'C': k = ConversionSpecifier::CArg; break;
204     case 'S': k = ConversionSpecifier::SArg; break;
205     // Objective-C.
206     case '@': k = ConversionSpecifier::ObjCObjArg; break;
207     // Glibc specific.
208     case 'm': k = ConversionSpecifier::PrintErrno; break;
209     // Apple-specific.
210     case 'D':
211       if (Target.getTriple().isOSDarwin())
212         k = ConversionSpecifier::DArg;
213       break;
214     case 'O':
215       if (Target.getTriple().isOSDarwin())
216         k = ConversionSpecifier::OArg;
217       break;
218     case 'U':
219       if (Target.getTriple().isOSDarwin())
220         k = ConversionSpecifier::UArg;
221       break;
222     // MS specific.
223     case 'Z':
224       if (Target.getTriple().isOSMSVCRT())
225         k = ConversionSpecifier::ZArg;
226   }
227   PrintfConversionSpecifier CS(conversionPosition, k);
228   FS.setConversionSpecifier(CS);
229   if (CS.consumesDataArgument() && !FS.usesPositionalArg())
230     FS.setArgIndex(argIndex++);
231 
232   if (k == ConversionSpecifier::InvalidSpecifier) {
233     // Assume the conversion takes one argument.
234     return !H.HandleInvalidPrintfConversionSpecifier(FS, Start, I - Start);
235   }
236   return PrintfSpecifierResult(Start, FS);
237 }
238 
ParsePrintfString(FormatStringHandler & H,const char * I,const char * E,const LangOptions & LO,const TargetInfo & Target)239 bool clang::analyze_format_string::ParsePrintfString(FormatStringHandler &H,
240                                                      const char *I,
241                                                      const char *E,
242                                                      const LangOptions &LO,
243                                                      const TargetInfo &Target) {
244 
245   unsigned argIndex = 0;
246 
247   // Keep looking for a format specifier until we have exhausted the string.
248   while (I != E) {
249     const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
250                                                             LO, Target, true);
251     // Did a fail-stop error of any kind occur when parsing the specifier?
252     // If so, don't do any more processing.
253     if (FSR.shouldStop())
254       return true;
255     // Did we exhaust the string or encounter an error that
256     // we can recover from?
257     if (!FSR.hasValue())
258       continue;
259     // We have a format specifier.  Pass it to the callback.
260     if (!H.HandlePrintfSpecifier(FSR.getValue(), FSR.getStart(),
261                                  I - FSR.getStart()))
262       return true;
263   }
264   assert(I == E && "Format string not exhausted");
265   return false;
266 }
267 
ParseFormatStringHasSArg(const char * I,const char * E,const LangOptions & LO,const TargetInfo & Target)268 bool clang::analyze_format_string::ParseFormatStringHasSArg(const char *I,
269                                                             const char *E,
270                                                             const LangOptions &LO,
271                                                             const TargetInfo &Target) {
272 
273   unsigned argIndex = 0;
274 
275   // Keep looking for a %s format specifier until we have exhausted the string.
276   FormatStringHandler H;
277   while (I != E) {
278     const PrintfSpecifierResult &FSR = ParsePrintfSpecifier(H, I, E, argIndex,
279                                                             LO, Target, false);
280     // Did a fail-stop error of any kind occur when parsing the specifier?
281     // If so, don't do any more processing.
282     if (FSR.shouldStop())
283       return false;
284     // Did we exhaust the string or encounter an error that
285     // we can recover from?
286     if (!FSR.hasValue())
287       continue;
288     const analyze_printf::PrintfSpecifier &FS = FSR.getValue();
289     // Return true if this a %s format specifier.
290     if (FS.getConversionSpecifier().getKind() == ConversionSpecifier::Kind::sArg)
291       return true;
292   }
293   return false;
294 }
295 
296 //===----------------------------------------------------------------------===//
297 // Methods on PrintfSpecifier.
298 //===----------------------------------------------------------------------===//
299 
getArgType(ASTContext & Ctx,bool IsObjCLiteral) const300 ArgType PrintfSpecifier::getArgType(ASTContext &Ctx,
301                                     bool IsObjCLiteral) const {
302   const PrintfConversionSpecifier &CS = getConversionSpecifier();
303 
304   if (!CS.consumesDataArgument())
305     return ArgType::Invalid();
306 
307   if (CS.getKind() == ConversionSpecifier::cArg)
308     switch (LM.getKind()) {
309       case LengthModifier::None:
310         return Ctx.IntTy;
311       case LengthModifier::AsLong:
312       case LengthModifier::AsWide:
313         return ArgType(ArgType::WIntTy, "wint_t");
314       case LengthModifier::AsShort:
315         if (Ctx.getTargetInfo().getTriple().isOSMSVCRT())
316           return Ctx.IntTy;
317       default:
318         return ArgType::Invalid();
319     }
320 
321   if (CS.isIntArg())
322     switch (LM.getKind()) {
323       case LengthModifier::AsLongDouble:
324         // GNU extension.
325         return Ctx.LongLongTy;
326       case LengthModifier::None:
327         return Ctx.IntTy;
328       case LengthModifier::AsInt32:
329         return ArgType(Ctx.IntTy, "__int32");
330       case LengthModifier::AsChar: return ArgType::AnyCharTy;
331       case LengthModifier::AsShort: return Ctx.ShortTy;
332       case LengthModifier::AsLong: return Ctx.LongTy;
333       case LengthModifier::AsLongLong:
334       case LengthModifier::AsQuad:
335         return Ctx.LongLongTy;
336       case LengthModifier::AsInt64:
337         return ArgType(Ctx.LongLongTy, "__int64");
338       case LengthModifier::AsIntMax:
339         return ArgType(Ctx.getIntMaxType(), "intmax_t");
340       case LengthModifier::AsSizeT:
341         // FIXME: How to get the corresponding signed version of size_t?
342         return ArgType();
343       case LengthModifier::AsInt3264:
344         return Ctx.getTargetInfo().getTriple().isArch64Bit()
345                    ? ArgType(Ctx.LongLongTy, "__int64")
346                    : ArgType(Ctx.IntTy, "__int32");
347       case LengthModifier::AsPtrDiff:
348         return ArgType(Ctx.getPointerDiffType(), "ptrdiff_t");
349       case LengthModifier::AsAllocate:
350       case LengthModifier::AsMAllocate:
351       case LengthModifier::AsWide:
352         return ArgType::Invalid();
353     }
354 
355   if (CS.isUIntArg())
356     switch (LM.getKind()) {
357       case LengthModifier::AsLongDouble:
358         // GNU extension.
359         return Ctx.UnsignedLongLongTy;
360       case LengthModifier::None:
361         return Ctx.UnsignedIntTy;
362       case LengthModifier::AsInt32:
363         return ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
364       case LengthModifier::AsChar: return Ctx.UnsignedCharTy;
365       case LengthModifier::AsShort: return Ctx.UnsignedShortTy;
366       case LengthModifier::AsLong: return Ctx.UnsignedLongTy;
367       case LengthModifier::AsLongLong:
368       case LengthModifier::AsQuad:
369         return Ctx.UnsignedLongLongTy;
370       case LengthModifier::AsInt64:
371         return ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64");
372       case LengthModifier::AsIntMax:
373         return ArgType(Ctx.getUIntMaxType(), "uintmax_t");
374       case LengthModifier::AsSizeT:
375         return ArgType(Ctx.getSizeType(), "size_t");
376       case LengthModifier::AsInt3264:
377         return Ctx.getTargetInfo().getTriple().isArch64Bit()
378                    ? ArgType(Ctx.UnsignedLongLongTy, "unsigned __int64")
379                    : ArgType(Ctx.UnsignedIntTy, "unsigned __int32");
380       case LengthModifier::AsPtrDiff:
381         // FIXME: How to get the corresponding unsigned
382         // version of ptrdiff_t?
383         return ArgType();
384       case LengthModifier::AsAllocate:
385       case LengthModifier::AsMAllocate:
386       case LengthModifier::AsWide:
387         return ArgType::Invalid();
388     }
389 
390   if (CS.isDoubleArg()) {
391     if (LM.getKind() == LengthModifier::AsLongDouble)
392       return Ctx.LongDoubleTy;
393     return Ctx.DoubleTy;
394   }
395 
396   if (CS.getKind() == ConversionSpecifier::nArg) {
397     switch (LM.getKind()) {
398       case LengthModifier::None:
399         return ArgType::PtrTo(Ctx.IntTy);
400       case LengthModifier::AsChar:
401         return ArgType::PtrTo(Ctx.SignedCharTy);
402       case LengthModifier::AsShort:
403         return ArgType::PtrTo(Ctx.ShortTy);
404       case LengthModifier::AsLong:
405         return ArgType::PtrTo(Ctx.LongTy);
406       case LengthModifier::AsLongLong:
407       case LengthModifier::AsQuad:
408         return ArgType::PtrTo(Ctx.LongLongTy);
409       case LengthModifier::AsIntMax:
410         return ArgType::PtrTo(ArgType(Ctx.getIntMaxType(), "intmax_t"));
411       case LengthModifier::AsSizeT:
412         return ArgType(); // FIXME: ssize_t
413       case LengthModifier::AsPtrDiff:
414         return ArgType::PtrTo(ArgType(Ctx.getPointerDiffType(), "ptrdiff_t"));
415       case LengthModifier::AsLongDouble:
416         return ArgType(); // FIXME: Is this a known extension?
417       case LengthModifier::AsAllocate:
418       case LengthModifier::AsMAllocate:
419       case LengthModifier::AsInt32:
420       case LengthModifier::AsInt3264:
421       case LengthModifier::AsInt64:
422       case LengthModifier::AsWide:
423         return ArgType::Invalid();
424     }
425   }
426 
427   switch (CS.getKind()) {
428     case ConversionSpecifier::sArg:
429       if (LM.getKind() == LengthModifier::AsWideChar) {
430         if (IsObjCLiteral)
431           return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
432                          "const unichar *");
433         return ArgType(ArgType::WCStrTy, "wchar_t *");
434       }
435       if (LM.getKind() == LengthModifier::AsWide)
436         return ArgType(ArgType::WCStrTy, "wchar_t *");
437       return ArgType::CStrTy;
438     case ConversionSpecifier::SArg:
439       if (IsObjCLiteral)
440         return ArgType(Ctx.getPointerType(Ctx.UnsignedShortTy.withConst()),
441                        "const unichar *");
442       if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
443           LM.getKind() == LengthModifier::AsShort)
444         return ArgType::CStrTy;
445       return ArgType(ArgType::WCStrTy, "wchar_t *");
446     case ConversionSpecifier::CArg:
447       if (IsObjCLiteral)
448         return ArgType(Ctx.UnsignedShortTy, "unichar");
449       if (Ctx.getTargetInfo().getTriple().isOSMSVCRT() &&
450           LM.getKind() == LengthModifier::AsShort)
451         return Ctx.IntTy;
452       return ArgType(Ctx.WideCharTy, "wchar_t");
453     case ConversionSpecifier::pArg:
454       return ArgType::CPointerTy;
455     case ConversionSpecifier::ObjCObjArg:
456       return ArgType::ObjCPointerTy;
457     default:
458       break;
459   }
460 
461   // FIXME: Handle other cases.
462   return ArgType();
463 }
464 
fixType(QualType QT,const LangOptions & LangOpt,ASTContext & Ctx,bool IsObjCLiteral)465 bool PrintfSpecifier::fixType(QualType QT, const LangOptions &LangOpt,
466                               ASTContext &Ctx, bool IsObjCLiteral) {
467   // %n is different from other conversion specifiers; don't try to fix it.
468   if (CS.getKind() == ConversionSpecifier::nArg)
469     return false;
470 
471   // Handle Objective-C objects first. Note that while the '%@' specifier will
472   // not warn for structure pointer or void pointer arguments (because that's
473   // how CoreFoundation objects are implemented), we only show a fixit for '%@'
474   // if we know it's an object (block, id, class, or __attribute__((NSObject))).
475   if (QT->isObjCRetainableType()) {
476     if (!IsObjCLiteral)
477       return false;
478 
479     CS.setKind(ConversionSpecifier::ObjCObjArg);
480 
481     // Disable irrelevant flags
482     HasThousandsGrouping = false;
483     HasPlusPrefix = false;
484     HasSpacePrefix = false;
485     HasAlternativeForm = false;
486     HasLeadingZeroes = false;
487     Precision.setHowSpecified(OptionalAmount::NotSpecified);
488     LM.setKind(LengthModifier::None);
489 
490     return true;
491   }
492 
493   // Handle strings next (char *, wchar_t *)
494   if (QT->isPointerType() && (QT->getPointeeType()->isAnyCharacterType())) {
495     CS.setKind(ConversionSpecifier::sArg);
496 
497     // Disable irrelevant flags
498     HasAlternativeForm = 0;
499     HasLeadingZeroes = 0;
500 
501     // Set the long length modifier for wide characters
502     if (QT->getPointeeType()->isWideCharType())
503       LM.setKind(LengthModifier::AsWideChar);
504     else
505       LM.setKind(LengthModifier::None);
506 
507     return true;
508   }
509 
510   // If it's an enum, get its underlying type.
511   if (const EnumType *ETy = QT->getAs<EnumType>())
512     QT = ETy->getDecl()->getIntegerType();
513 
514   // We can only work with builtin types.
515   const BuiltinType *BT = QT->getAs<BuiltinType>();
516   if (!BT)
517     return false;
518 
519   // Set length modifier
520   switch (BT->getKind()) {
521   case BuiltinType::Bool:
522   case BuiltinType::WChar_U:
523   case BuiltinType::WChar_S:
524   case BuiltinType::Char16:
525   case BuiltinType::Char32:
526   case BuiltinType::UInt128:
527   case BuiltinType::Int128:
528   case BuiltinType::Half:
529     // Various types which are non-trivial to correct.
530     return false;
531 
532 #define SIGNED_TYPE(Id, SingletonId)
533 #define UNSIGNED_TYPE(Id, SingletonId)
534 #define FLOATING_TYPE(Id, SingletonId)
535 #define BUILTIN_TYPE(Id, SingletonId) \
536   case BuiltinType::Id:
537 #include "clang/AST/BuiltinTypes.def"
538     // Misc other stuff which doesn't make sense here.
539     return false;
540 
541   case BuiltinType::UInt:
542   case BuiltinType::Int:
543   case BuiltinType::Float:
544   case BuiltinType::Double:
545     LM.setKind(LengthModifier::None);
546     break;
547 
548   case BuiltinType::Char_U:
549   case BuiltinType::UChar:
550   case BuiltinType::Char_S:
551   case BuiltinType::SChar:
552     LM.setKind(LengthModifier::AsChar);
553     break;
554 
555   case BuiltinType::Short:
556   case BuiltinType::UShort:
557     LM.setKind(LengthModifier::AsShort);
558     break;
559 
560   case BuiltinType::Long:
561   case BuiltinType::ULong:
562     LM.setKind(LengthModifier::AsLong);
563     break;
564 
565   case BuiltinType::LongLong:
566   case BuiltinType::ULongLong:
567     LM.setKind(LengthModifier::AsLongLong);
568     break;
569 
570   case BuiltinType::LongDouble:
571     LM.setKind(LengthModifier::AsLongDouble);
572     break;
573   }
574 
575   // Handle size_t, ptrdiff_t, etc. that have dedicated length modifiers in C99.
576   if (isa<TypedefType>(QT) && (LangOpt.C99 || LangOpt.CPlusPlus11))
577     namedTypeToLengthModifier(QT, LM);
578 
579   // If fixing the length modifier was enough, we might be done.
580   if (hasValidLengthModifier(Ctx.getTargetInfo())) {
581     // If we're going to offer a fix anyway, make sure the sign matches.
582     switch (CS.getKind()) {
583     case ConversionSpecifier::uArg:
584     case ConversionSpecifier::UArg:
585       if (QT->isSignedIntegerType())
586         CS.setKind(clang::analyze_format_string::ConversionSpecifier::dArg);
587       break;
588     case ConversionSpecifier::dArg:
589     case ConversionSpecifier::DArg:
590     case ConversionSpecifier::iArg:
591       if (QT->isUnsignedIntegerType() && !HasPlusPrefix)
592         CS.setKind(clang::analyze_format_string::ConversionSpecifier::uArg);
593       break;
594     default:
595       // Other specifiers do not have signed/unsigned variants.
596       break;
597     }
598 
599     const analyze_printf::ArgType &ATR = getArgType(Ctx, IsObjCLiteral);
600     if (ATR.isValid() && ATR.matchesType(Ctx, QT))
601       return true;
602   }
603 
604   // Set conversion specifier and disable any flags which do not apply to it.
605   // Let typedefs to char fall through to int, as %c is silly for uint8_t.
606   if (!isa<TypedefType>(QT) && QT->isCharType()) {
607     CS.setKind(ConversionSpecifier::cArg);
608     LM.setKind(LengthModifier::None);
609     Precision.setHowSpecified(OptionalAmount::NotSpecified);
610     HasAlternativeForm = 0;
611     HasLeadingZeroes = 0;
612     HasPlusPrefix = 0;
613   }
614   // Test for Floating type first as LongDouble can pass isUnsignedIntegerType
615   else if (QT->isRealFloatingType()) {
616     CS.setKind(ConversionSpecifier::fArg);
617   }
618   else if (QT->isSignedIntegerType()) {
619     CS.setKind(ConversionSpecifier::dArg);
620     HasAlternativeForm = 0;
621   }
622   else if (QT->isUnsignedIntegerType()) {
623     CS.setKind(ConversionSpecifier::uArg);
624     HasAlternativeForm = 0;
625     HasPlusPrefix = 0;
626   } else {
627     llvm_unreachable("Unexpected type");
628   }
629 
630   return true;
631 }
632 
toString(raw_ostream & os) const633 void PrintfSpecifier::toString(raw_ostream &os) const {
634   // Whilst some features have no defined order, we are using the order
635   // appearing in the C99 standard (ISO/IEC 9899:1999 (E) 7.19.6.1)
636   os << "%";
637 
638   // Positional args
639   if (usesPositionalArg()) {
640     os << getPositionalArgIndex() << "$";
641   }
642 
643   // Conversion flags
644   if (IsLeftJustified)    os << "-";
645   if (HasPlusPrefix)      os << "+";
646   if (HasSpacePrefix)     os << " ";
647   if (HasAlternativeForm) os << "#";
648   if (HasLeadingZeroes)   os << "0";
649 
650   // Minimum field width
651   FieldWidth.toString(os);
652   // Precision
653   Precision.toString(os);
654   // Length modifier
655   os << LM.toString();
656   // Conversion specifier
657   os << CS.toString();
658 }
659 
hasValidPlusPrefix() const660 bool PrintfSpecifier::hasValidPlusPrefix() const {
661   if (!HasPlusPrefix)
662     return true;
663 
664   // The plus prefix only makes sense for signed conversions
665   switch (CS.getKind()) {
666   case ConversionSpecifier::dArg:
667   case ConversionSpecifier::DArg:
668   case ConversionSpecifier::iArg:
669   case ConversionSpecifier::fArg:
670   case ConversionSpecifier::FArg:
671   case ConversionSpecifier::eArg:
672   case ConversionSpecifier::EArg:
673   case ConversionSpecifier::gArg:
674   case ConversionSpecifier::GArg:
675   case ConversionSpecifier::aArg:
676   case ConversionSpecifier::AArg:
677     return true;
678 
679   default:
680     return false;
681   }
682 }
683 
hasValidAlternativeForm() const684 bool PrintfSpecifier::hasValidAlternativeForm() const {
685   if (!HasAlternativeForm)
686     return true;
687 
688   // Alternate form flag only valid with the oxXaAeEfFgG conversions
689   switch (CS.getKind()) {
690   case ConversionSpecifier::oArg:
691   case ConversionSpecifier::OArg:
692   case ConversionSpecifier::xArg:
693   case ConversionSpecifier::XArg:
694   case ConversionSpecifier::aArg:
695   case ConversionSpecifier::AArg:
696   case ConversionSpecifier::eArg:
697   case ConversionSpecifier::EArg:
698   case ConversionSpecifier::fArg:
699   case ConversionSpecifier::FArg:
700   case ConversionSpecifier::gArg:
701   case ConversionSpecifier::GArg:
702     return true;
703 
704   default:
705     return false;
706   }
707 }
708 
hasValidLeadingZeros() const709 bool PrintfSpecifier::hasValidLeadingZeros() const {
710   if (!HasLeadingZeroes)
711     return true;
712 
713   // Leading zeroes flag only valid with the diouxXaAeEfFgG conversions
714   switch (CS.getKind()) {
715   case ConversionSpecifier::dArg:
716   case ConversionSpecifier::DArg:
717   case ConversionSpecifier::iArg:
718   case ConversionSpecifier::oArg:
719   case ConversionSpecifier::OArg:
720   case ConversionSpecifier::uArg:
721   case ConversionSpecifier::UArg:
722   case ConversionSpecifier::xArg:
723   case ConversionSpecifier::XArg:
724   case ConversionSpecifier::aArg:
725   case ConversionSpecifier::AArg:
726   case ConversionSpecifier::eArg:
727   case ConversionSpecifier::EArg:
728   case ConversionSpecifier::fArg:
729   case ConversionSpecifier::FArg:
730   case ConversionSpecifier::gArg:
731   case ConversionSpecifier::GArg:
732     return true;
733 
734   default:
735     return false;
736   }
737 }
738 
hasValidSpacePrefix() const739 bool PrintfSpecifier::hasValidSpacePrefix() const {
740   if (!HasSpacePrefix)
741     return true;
742 
743   // The space prefix only makes sense for signed conversions
744   switch (CS.getKind()) {
745   case ConversionSpecifier::dArg:
746   case ConversionSpecifier::DArg:
747   case ConversionSpecifier::iArg:
748   case ConversionSpecifier::fArg:
749   case ConversionSpecifier::FArg:
750   case ConversionSpecifier::eArg:
751   case ConversionSpecifier::EArg:
752   case ConversionSpecifier::gArg:
753   case ConversionSpecifier::GArg:
754   case ConversionSpecifier::aArg:
755   case ConversionSpecifier::AArg:
756     return true;
757 
758   default:
759     return false;
760   }
761 }
762 
hasValidLeftJustified() const763 bool PrintfSpecifier::hasValidLeftJustified() const {
764   if (!IsLeftJustified)
765     return true;
766 
767   // The left justified flag is valid for all conversions except n
768   switch (CS.getKind()) {
769   case ConversionSpecifier::nArg:
770     return false;
771 
772   default:
773     return true;
774   }
775 }
776 
hasValidThousandsGroupingPrefix() const777 bool PrintfSpecifier::hasValidThousandsGroupingPrefix() const {
778   if (!HasThousandsGrouping)
779     return true;
780 
781   switch (CS.getKind()) {
782     case ConversionSpecifier::dArg:
783     case ConversionSpecifier::DArg:
784     case ConversionSpecifier::iArg:
785     case ConversionSpecifier::uArg:
786     case ConversionSpecifier::UArg:
787     case ConversionSpecifier::fArg:
788     case ConversionSpecifier::FArg:
789     case ConversionSpecifier::gArg:
790     case ConversionSpecifier::GArg:
791       return true;
792     default:
793       return false;
794   }
795 }
796 
hasValidPrecision() const797 bool PrintfSpecifier::hasValidPrecision() const {
798   if (Precision.getHowSpecified() == OptionalAmount::NotSpecified)
799     return true;
800 
801   // Precision is only valid with the diouxXaAeEfFgGs conversions
802   switch (CS.getKind()) {
803   case ConversionSpecifier::dArg:
804   case ConversionSpecifier::DArg:
805   case ConversionSpecifier::iArg:
806   case ConversionSpecifier::oArg:
807   case ConversionSpecifier::OArg:
808   case ConversionSpecifier::uArg:
809   case ConversionSpecifier::UArg:
810   case ConversionSpecifier::xArg:
811   case ConversionSpecifier::XArg:
812   case ConversionSpecifier::aArg:
813   case ConversionSpecifier::AArg:
814   case ConversionSpecifier::eArg:
815   case ConversionSpecifier::EArg:
816   case ConversionSpecifier::fArg:
817   case ConversionSpecifier::FArg:
818   case ConversionSpecifier::gArg:
819   case ConversionSpecifier::GArg:
820   case ConversionSpecifier::sArg:
821     return true;
822 
823   default:
824     return false;
825   }
826 }
hasValidFieldWidth() const827 bool PrintfSpecifier::hasValidFieldWidth() const {
828   if (FieldWidth.getHowSpecified() == OptionalAmount::NotSpecified)
829       return true;
830 
831   // The field width is valid for all conversions except n
832   switch (CS.getKind()) {
833   case ConversionSpecifier::nArg:
834     return false;
835 
836   default:
837     return true;
838   }
839 }
840